HttpRequestMessage.GetClientCertificate() 在 Web API 中返回 null

本文关键字:API 返回 null Web GetClientCertificate HttpRequestMessage | 更新日期: 2023-09-27 17:56:26

我有一个 .NET4.5 WebAPI 2 应用,使用 SSL 客户端证书进行一些与安全相关的自定义检查。

调试应用程序时,无论我到目前为止尝试了什么,request.GetClientCertificate()都会返回任何服务调用的null

测试的代码:

基本上,在我的服务方面,我有一个这样的方法:

class CertificateChecker : ICertificateChecker
{
    public bool Check(HttpRequestMessage request)
    {
        var cert = request.GetClientCertificate();
    }
}

我的单元使用附加到请求的客户端证书进行测试request.Properties.Add(HttpPropertyKeys.ClientCertificateKey, cert)传递(证书完全按预期出来,验证工作,等等)。

但是,当我使用带有调用实际 WebAPI 应用的HttpClient的测试时,在服务端的request.GetClientCertificate()行设置断点,同一行返回 null。

这是我尝试过的:

客户端证书:

  • 创建了一个假 CA 并将其放入受信任的 CA 存储中(尝试了本地计算机和当前用户)。
  • 创建了由该假 CA 签名的客户端身份验证 (1.3.6.1.5.5.7.3.2) 证书,并将其放入个人存储(本地计算机和当前用户)中。

(基本上,关注 https://www.piotrwalat.net/client-certificate-authentication-in-asp-net-web-api-and-windows-store-apps/和类似的博客)

在我的测试中,使用 HttpClient 调用服务,通过以下方式附加客户端证书(这些方法都不起作用):

  • 使用WebRequestHandlerClientCertificateOptions设置为手动,并将证书添加到ClientCertificates集合中。

    using (var handler = new WebRequestHandler())
    {
         var cert = GetTestCert();
         handler.ClientCertificateOptions = ClientCertificateOption.Manual;
         handler.ClientCertificates.Add(cert);
         // and so on...
    }
    
  • 使用 HttpRequestMessage ,将证书添加为键设置为 HttpPropertyKeys.ClientCertificateKey 的属性(此方法在如上所述进行单元测试时有效)。

    request.Properties.Add(HttpPropertyKeys.ClientCertificateKey, cert);
    

在这两种情况下,cert变量都设置为预期的X509Certificate2对象。

好客:

    IISExpress
  • :已尝试在 IISExpress 中运行该应用。

    编辑了应用程序主机.config,iisClientCertificateMappingAuthentication enabled设置为"true"和以下访问设置(均无效):

    <access sslFlags="Ssl, SslNegotiateCert" />
    <access sslFlags="SslNegotiateCert" />
    
  • 本地 IIS将 Web 应用设置为在本地计算机上的 IIS 中运行

    • IIS 中的站点使用受信任的证书配置了 HTTPS 绑定。
    • 配置为使用 https 协议并启用 IIS 客户端证书映射身份验证的 Web 应用。
    • 尝试了访问选项组合(Ssl, SslNegotiateCertSslNegotiateCert)(通过配置编辑器)

在这两种情况下,当使用 Web 浏览器通过 https url 访问 Web api 时,我会毫无问题地显示主控制器的索引视图(因此,服务器端证书是受信任的)。

HttpRequestMessage.GetClientCertificate() 在 Web API 中返回 null

我知道

它有点旧,但我遇到了同样的问题,我通过以下方法解决了它 fg这篇文章:

https://improveandrepeat.com/2017/07/how-to-configure-iis-express-to-accept-ssl-client-certificates/

问题是 IIS 服务器上的配置,也可以在 IIS Express 上修改。我报告它,以防链接不可用。

对于

IIS,请更改服务器配置文件,对于 IIS Express 修改 解决方案下的文件位于 .vs''config''applicationhost.config

搜索在元素中调用的 xml 元素:

<security>
  <access sslFlags="None" />

默认配置不支持 SSL 客户端证书。 您需要修改 sslFlags 属性以包含以下选项: Ssl, SslNegotiateCert, SslRequireCert

<security>
        <access sslFlags="Ssl, SslNegotiateCert, SslRequireCert" />

下一步是找到元素 :

<iisClientCertificateMappingAuthentication enabled="false"></iisClientCertificateMappingAuthentication>

如果将启用更改为 true,IIS Express 将开始接受客户端 证书:

<iisClientCertificateMappingAuthentication enabled="true">
            </iisClientCertificateMappingAuthentication>

您现在需要重新启动Visual Studio和IIS Express。IIS Express 可以 使用系统托盘中的图标重新启动。

从现在开始,您将被要求提供客户端证书,您可以 在Visual Studio中调试整个应用程序。这可能看起来不行 像一个很大的改进,但相信我,它使调试变得更加简单。

希望这可以帮助其他人:-)

关于您的问题的非常详细的信息。

我将假设问题出在附加带有 HttpClient 的客户端证书上,因为在这种情况下您无法在服务器端查看证书。所有托管和服务器端证书配置听起来都不错。

  1. 我会确保您附加的 X509Certificate2 cert 变量是存在于本地证书存储中的公钥(我不确定您将其存储在哪个存储位置)(您可以使用 mmc.exe 进行检查)。还要确保公钥带有私钥,因为 HttpClient 需要它来签署请求。

  2. 在代码片段中,您必须在其余代码之前using (var handler = new WebRequestHandler())。确保您也在使用中构建HttpClient client = new HttpClient(handler),否则处理程序将被释放。

否则,处理程序创建看起来不错。

祝你好运!