HttpClient与客户端证书一起重用

本文关键字:一起 证书 客户端 HttpClient | 更新日期: 2023-09-27 18:05:36

我在几个地方读到(如这里,这里或这里),这是一个坏的做法,在请求后直接处理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

HttpClient与客户端证书一起重用

你的修复应该是这样的:

handler.PreAuthenticate = true;

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