HttpClient与客户端证书一起重用

我已经在几个地方(比如这里 , 这里或这里 )读过, 在请求之后直接处理HttpClient是一种不好的做法,最好在所有请求完成后处理它,以允许重用连接。

为了尝试这一点,我创建了一个HttpClient实例并以这种方式添加到我的类中的静态字段:

public class Test { private static X509Certificate2 _certificate; private static HttpClient HttpClient { get; set; } ... public Test() { ... if (HttpClient == null) { LoadCertificate(); ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12 | SecurityProtocolType.Ssl3; var handler = new WebRequestHandler(); handler.ClientCertificates.Add(_certificate); HttpClient = new HttpClient(handler, false); } } private void LoadCertificate() { using (var store = new X509Store(StoreName.My, CertificateStoreLocation)) { store.Open(OpenFlags.ReadOnly); var certificates = store.Certificates.Find(X509FindType.FindBySubjectName, CertificateFriendlyName, true); if (certificates.Count != 1) throw new ArgumentException( $"Cannot find a valid certificate with name {CertificateFriendlyName} in {CertificateStoreLocation}"); _certificate = certificates[0]; store.Close(); } ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; } } 

然后,我使用我的实例通过此命令调用Web服务:

 var result = await HttpClient.PostAsJsonAsync(completeUri, request); 

我第一次运行代码时,一切正常,我得到了正确的响应,但随后,我从服务器获得了未经授权的声明,告诉我我没有使用客户端证书。

就像以下调用一样, WebRequestHandler没有被考虑在内。

您的修复应如下所示:

 handler.PreAuthenticate = true; 

建立与服务的连接后,您可以重新使用它与使用具有不同身份validation信息的不同客户端进行通信。 这意味着,服务需要知道哪个客户端每次都发送请求,否则可能是安全漏洞 – 例如在最后连接的客户端下执行请求。 这取决于您的身份validation机制,但基本上WebRequestHandler在第一个请求后设置标志IsAuthenticated ,并停止在下一个请求上发送auth信息。 PreAuthenticate选项强制在每个请求上发送身份validation信息。