在创建 HttpClient 的相同位置访问 HttpClientHandler

Accessing HttpClientHandler in the same place as HttpClient is created

我有一项服务请求 URL 并验证服务器 SSL 证书。代码在完整的 .NET 框架中已经 运行 顺利地使用 HttpWebRequest,但现在我想将它迁移到 HttpClient 和 .NET Core。我可以这样获得证书(该方法在多篇博文和堆栈溢出答案中被推荐):

X509Certificate2 cert = null;

var httpClient = new HttpClient(new HttpClientHandler
{
    ServerCertificateCustomValidationCallback = (request, certificate, chain, errors) =>
    {
        cert = certificate;
        return true;
    }
});

httpClient.GetAsync(...);

这里的问题是我不断创建新的 HttpClient 实例,不推荐这样做。我想移动到 HttpClientFactory,为什么我在设置代码中添加以下内容:

services
    .AddHttpClient("sslclient", x =>
    {
        ...
    })
    .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
    {
        ServerCertificateCustomValidationCallback = (request, certificate, chain, errors) =>
        {
            return true;
        }
    });

现在的挑战是代码创建的客户端不再有权访问 ServerCertificateCustomValidationCallback:

var httpClient = httpClientFactory.CreateClient("sslclient");

有人知道如何解决这个问题吗?

Reddit 上的某人 suggested 以下解决方案。一旦调用 AddHttpClient,就不能再修改 HttpClientHandler。但是可以共享资源:

var certificates= new ConcurrentDictionary<string, X509Certificate2>();
services.AddSingleton(certificates);
services
    .AddHttpClient("sslclient", x =>
    {
        ...
    })
    .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler
    {
        ServerCertificateCustomValidationCallback = (request, certificate, chain, errors) =>
        {
            certificates.TryAdd(request.RequestUri.Host, new X509Certificate2(certificate));
            return true;
        }
    });

在发出 HTTP 请求的代码中,您还需要注入 certificates 字典。发出请求后,您可以在字典中查找证书:

var response = await httpClient.GetAsync(url);
if (certificates.ContainsKey(uri.Host))
{
    // Happy days!
}