问题描述
我无法使用 HttpClient 类在 Windows 上使用 .NET Core 发送客户端证书.
I am unable to get the HttpClient class to send a client certificate using .NET Core on Windows.
这是我使用的代码:
X509Certificate2 certificate = new X509Certificate2(@"C:Repossellyclient1.pfx", "password");
HttpClientHandler handler = new HttpClientHandler();
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.ServerCertificateCustomValidationCallback = (a,b,c,d) => { return true; };
handler.ClientCertificates.Add(certificate);
HttpClient client = new HttpClient(handler);
var content = new StringContent("");
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
client.PostAsync("https://client2:5002/api/values", content).Wait();
代码在 Linux (Ubuntu 16.04) 上按预期工作(显然,证书路径已更改).它不适用于 Windows.
The code works as expected on Linux (Ubuntu 16.04) (obviously, with the path to the certificate changed). It does not work on Windows.
查看 Wireshark 中的交换,客户端在 Windows (10 v1703) 上运行时不发送证书.
Looking at the exchange in Wireshark, the client does not send the certificate when running on Windows (10 v1703).
我使用 .NET Framework(使用WebRequestHandler"而不是HttpClientHandler")运行了类似的代码.它正确发送客户端证书.
I have run similar code using .NET Framework (using 'WebRequestHandler' instead of 'HttpClientHandler'). It correctly sends the client certificate.
我在网上找到了以下,但与那里描述的问题不同,服务器证书回调被执行.我确实自己生成了证书,但它们都由根 CA(安装在客户端和服务器上)签名,并且所有详细信息都是正确的.
I found the following online, but unlike the problem described there, the server certificate callback is executed. I did generate the certificates myself, but they are all signed by a Root CA, (which is installed on both client and server) and all the details are correct.
我还发现了这个,这表明客户端证书可以在 Windows 上的 .NET Core 上使用 HttpClient.
I also found this, which suggests that client certificates do work with HttpClient on .NET Core on Windows.
我也尝试过明确设置 TLS 版本,但问题仍然存在.
I have also tried explicitly setting the TLS version, however the problem persists.
我使用 Kestrel 作为网络服务器.其配置如下:
I am using Kestrel as the web server. It is configured as follows:
.UseKestrel(options =>
{
var sslOps = new HttpsConnectionFilterOptions();
sslOps.ClientCertificateMode = ClientCertificateMode.RequireCertificate;
sslOps.ClientCertificateValidation = CheckClientCertificateLogic.CheckClientCertificate;
sslOps.ServerCertificate = new X509Certificate2(@"C:Repossellyclient2.pfx", "password");
options.UseHttps(sslOps);
})
'ClientCertificateValidation' 回调不会对从 Windows 客户端收到的请求执行;可能是因为它还没有收到证书供它检查...
The 'ClientCertificateValidation' callback does not execute on requests received from a Windows client; probably because it hasn't received a certificate for it to check...
这是 .NET Core 中的错误吗?有解决方法吗?
Is this a bug in .NET Core? Is there a workaround?
推荐答案
不完全确定我重现这个问题是否是由于相同的根本原因.但是,我遇到了同样的问题,结果证明没有发送证书,因为客户端无法验证它.在客户端的证书"MMC 管理单元中将颁发者证书添加到我的受信任颁发者列表后,Windows 可以验证该证书并且 HttpClient 开始发送它.如果您有自签名证书,那么我假设您可以将其添加到受信任的颁发者存储中.这是在 .Net 4.6.1 上测试的.
Not entirely sure if my reproducing this issue is due to the same root cause. However, I had the same problem and it turns out that the certificate is not sent because the client cannot validate it. After adding the issuer certificate to my trusted issuers list in the "Certificates" MMC snap-in on the client, Windows can validate the certificate and HttpClient starts to send it. If you have a self-signed certificate then I assume that you can add that to the trusted issuers store instead. This was tested on .Net 4.6.1.
WinHTTP中设置客户端证书的相关代码是此处.当您阅读 GetEligibleClientCertificate 的代码注释时,您会看到 MS 已计划添加额外的证书过滤,以删除与受信任颁发者列表不匹配的任何内容.他们只是没有考虑过将证书保存在文件中而不关心证书存储的用例.
The relevant code that is setting the client certificate in WinHTTP is here. When you read code comments for GetEligibleClientCertificate, you see that MS has been planning to add additional filtering of the certificates that removes anything that isn't matched by the trusted issuers list. They simply haven't thought about the use case where you keep your certificate in a file and don't care about the certificate store.
这篇关于HttpClient 不使用 .NET Core 在 Windows 上发送客户端证书的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!