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信息。