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, SslNegotiateCert
和SslNegotiateCert
)(通过配置编辑器)
在这两种情况下,当使用Web浏览器通过https url访问web api时,我得到家庭控制器的索引视图以显示没有问题(因此,服务器端证书是可信的)。
有关您的问题的详细信息。
我将假设问题是附加客户端证书w / HttpClient,因为在那种情况下你无法在服务器端查看证书。 所有托管和服务器端证书配置听起来都不错。
-
我要确保您附加的
X509Certificate2 cert
变量是本地证书存储中存在的公钥(我不确定您存储的是哪个存储位置)(您可以使用mmc.exe进行检查)。 还要确保公钥具有私钥,因为HttpClient需要对其进行签名。 -
在您的代码片段中,您在代码的其余部分之前
using (var handler = new WebRequestHandler())
。 确保你在使用中构建你的HttpClient client = new HttpClient(handler)
,否则处理程序将被处理掉。
否则处理程序创建看起来很好。
祝好运!