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

我有一个.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)传递附加到请求的客户端证书进行测试(证书完全符合预期,validation工作,等等)。

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

这是我尝试过的:

客户证书:

  • 创建了假CA并将其放入可信CA存储(尝试使用LocalMachine和当前用户)。
  • 创建由该假CA签名的客户端身份validation(1.3.6.1.5.5.7.3.2)证书,并将其放入个人存储(LocalMachine和当前用户)。

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

在我使用HttpClient调用服务的测试中,以下列方式附加了客户端证书(没有一个工作):

  • 使用WebRequestHandler ,将ClientCertificateOptions设置为Manual,并将cert添加到ClientCertificates集合中。

     using (var handler = new WebRequestHandler()) { var cert = GetTestCert(); handler.ClientCertificateOptions = ClientCertificateOption.Manual; handler.ClientCertificates.Add(cert); // and so on... } 
  • 使用HttpRequestMessage ,将cert作为属性添加,并将密钥设置为HttpPropertyKeys.ClientCertificateKey (此方法在上述unit testing时有效)。

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

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

主机:

  • IISExpress:试图在IISExpress中运行该应用程序。

    iisClientCertificateMappingAuthentication enabled编辑applicationhost.config设置为“true”以及以下访问设置(均未使用):

       
  • 本地IIS将​​Web应用程序设置为在本地计算机上的IIS中运行

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

在这两种情况下,当使用Web浏览器通过https url访问web api时,我得到家庭控制器的索引视图以显示没有问题(因此,服务器端证书是可信的)。

有关您的问题的详细信息。

我将假设问题是附加客户端证书w / HttpClient,因为在那种情况下你无法在服务器端查看证书。 所有托管和服务器端证书配置听起来都不错。

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

  2. 在您的代码片段中,您在代码的其余部分之前using (var handler = new WebRequestHandler()) 。 确保你在使用中构建你的HttpClient client = new HttpClient(handler) ,否则处理程序将被处理掉。

否则处理程序创建看起来很好。

祝好运!