ASP.NET Core (3.1) re-using self-hosted (Kestrel) 应用程序中的 IIS 证书

ASP.NET Core (3.1) re-using IIS certificate in self-hosted (Kestrel) application

我有一个 ASP.NET 核心 (3.1) 应用程序,它是 self-hosted 和 运行 作为服务。我想为它公开一个 HTTPS 端点。在同一台机器上安装了一个 IIS,其中安装了已配置的 https 和证书:

证书似乎存储在本地计算机证书存储中:

我也可以通过 powershell 列出它:

> get-childitem cert:\LocalMachine\My\ | format-table NotAfter, Subject

NotAfter            Subject
--------            -------
27.10.2023 07:38:45 <irrelevant>
08.03.2022 09:52:44 CN=a7642e58-2cdf-4e9b-a277-60fad84d7c64, DC=3336d6b0-b132-47ee-a49b-3ab470a5336e
23.02.2022 21:51:53 CN=a7642e58-2cdf-4e9b-a277-60fad84d7c64, DC=3336d6b0-b132-47ee-a49b-3ab470a5336e
27.10.2031 06:48:06 CN=a7642e58-2cdf-4e9b-a277-60fad84d7c64
26.10.2024 10:41:03 E=****.com, CN=****, OU=IT, O=****, L=****, S=***, C=**

我将 appsettings.json 更改为使用商店的证书:

{
  "Logging": {
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Warning"
    }
  },
  "AllowedHosts": "*",
  "Kestrel": {
    "EndPoints": {
      "Http": {
        "Url": "http://*:5000"
      },
      "HttpsDefaultCert": {
        "Url": "https://*:5001"
      }
    },
    "Certificates": {
      "Default": {
        "Subject": "E=****.com, CN=****, OU=IT, O=****, L=****, S=***, C=**",
        "Store": "My",
        "Location": "LocalMachine",
        "AllowInvalid": "true"
      }
    }
  }
}

但这似乎不起作用。我总是收到以下错误:

 System.InvalidOperationException: The requested certificate E=****.com, CN=****, OU=IT, O=****, L=****, S=***, C=** could not be found in LocalMachine/My with AllowInvalid setting: True

我不知道可能是什么问题。 我认为唯一可能有问题的是证书主题实际上包含主题中的换行符:

我不知道这是不是问题所在,我不知道如何在 appsettings.json 中输入它,因为无法输入多行值。

我参考了在 Kestrel 上为 Asp.NetCore 应用程序 运行 配置 SSL 证书的文档。

我注意到一些 URL 和端口设置也存储在 Properties/LaunchSettings.json 文件中。

看这里:Configure endpoints for the ASP.NET Core Kestrel web server

此外,我注意到您已将证书置于默认值下。我找到了其他配置证书的方法。你可以试试看。

在下面的appsettings.json例子中:

  • AllowInvalid 设置为 true 以允许使用无效证书(例如,self-signed 证书)。
  • 任何未指定证书的 HTTPS 端点(下例中的 HttpsDefaultCert)回退到 Certificates:Default 下定义的证书或开发证书。

{
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://localhost:5000"
      },
      "HttpsInlineCertFile": {
        "Url": "https://localhost:5001",
        "Certificate": {
          "Path": "<path to .pfx file>",
          "Password": "$CREDENTIAL_PLACEHOLDER$"
        }
      },
      "HttpsInlineCertAndKeyFile": {
        "Url": "https://localhost:5002",
        "Certificate": {
          "Path": "<path to .pem/.crt file>",
          "KeyPath": "<path to .key file>",
          "Password": "$CREDENTIAL_PLACEHOLDER$"
        }
      },
      "HttpsInlineCertStore": {
        "Url": "https://localhost:5003",
        "Certificate": {
          "Subject": "<subject; required>",
          "Store": "<certificate store; required>",
          "Location": "<location; defaults to CurrentUser>",
          "AllowInvalid": "<true or false; defaults to false>"
        }
      },
      "HttpsDefaultCert": {
        "Url": "https://localhost:5004"
      }
    },
    "Certificates": {
      "Default": {
        "Path": "<path to .pfx file>",
        "Password": "$CREDENTIAL_PLACEHOLDER$"
      }
    }
  }
}

架构说明:

  • 端点名称是 case-insensitive。例如,HTTPS 和 Https 是等价的。
  • 每个端点都需要 Url 参数。此参数的格式与 top-level Urls 配置参数相同,只是它仅限于单个值。
  • 这些端点取代了 top-level Url 配置中定义的端点,而不是添加到它们中。通过 Listen 在代码中定义的端点与配置部分中定义的端点累加。
  • 证书部分是可选的。如果未指定 Certificate 部分,则使用 Certificates:Default 中定义的默认值。如果没有可用的默认值,则使用开发证书。如果没有默认值且开发证书不存在,服务器将抛出异常并无法启动。
  • 证书部分支持多个证书来源。
  • 可以在配置中定义任意数量的端点,只要它们不会导致端口冲突。

参考:Replace the default certificate from configuration

我已经找到问题所在。 Kestrel 在搜索证书时使用 FindBySubjectName

FindBySubjectName 执行 sub-string 搜索并且 不匹配 证书的完整主题。如果您的证书主题类似于 'CN=my-certificate',则搜索 'CN=my-certificate' 将找不到任何内容。仅搜索 'my-certificate' 即可。

附加说明:除了指定正确的搜索表达式外,请确保您运行正在使用应用程序的帐户有足够的权限从证书存储中读取证书。证书确实有 ACL,因此您不必 运行 您的应用程序作为管理员。