【问题标题】:HttpClientHandler (.NET Core) raise error when WebRequestHandler (.NET Framework 4.6.1) works as expected当 WebRequestHandler (.NET Framework 4.6.1) 按预期工作时,HttpClientHandler (.NET Core) 引发错误
【发布时间】:2021-03-16 05:48:00
【问题描述】:

我正在将一个应用程序从 .NET Framework 4.6.1 迁移到 .NET 5。在旧应用程序中,我有一个使用证书、用户和密码发送请求的功能,它与 WebRequestHandler。

由于在 .NET Core 中这不再可用,我不得不将其替换为 HttpClientHandler 并且收到以下错误:身份验证失败。收到的消息出乎意料或格式错误。

有人可以帮我吗?

这是我的初始代码:

            WebRequestHandler handler = new WebRequestHandler();

            X509Certificate2 certificate = GetMyX509Certificate(certificateThumbprint);
            handler.ClientCertificates.Add(certificate);  
    
            HttpClient client = new HttpClient(handler);
            client.BaseAddress = new Uri(url);
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

            client .DefaultRequestHeaders.Add("segment", segment);

            var byteArray = Encoding.ASCII.GetBytes($"{userName}:{password}");
            client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));

            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

            HttpResponseMessage userExistsResponse = await client.GetAsync($"Users?filter=...");

这是不工作的代码:

        HttpClientHandler handler = new HttpClientHandler();
        handler.SslProtocols = SslProtocols.Tls12;

        X509Certificate2 certificate = GetMyX509Certificate(certificateThumbprint);
        handler.ClientCertificates.Add(certificate);
        
        HttpClient client = new HttpClient(handler);
        client.BaseAddress = new Uri(url);            
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
       
        client.DefaultRequestHeaders.Add("segment", segment);
        
        var byteArray = new UTF8Encoding().GetBytes($"{userName}:{password}");
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));
       
         var request = new HttpRequestMessage(HttpMethod.Get, client.BaseAddress + "/Users?filter=...");
         var response = await client.SendAsync(request);

【问题讨论】:

  • 发布实际的完整异常文本,而不仅仅是消息的一部分。 HttpClient 没有任何问题,尽管这段代码有几个不相关的问题。也许旧代码掩盖了证书错误?也许旧代码 没有 使用 TLS1.2 ?也许 服务器 使用 TLS1.3,所以对 SSL 版本进行硬编码会导致问题?
  • 您可以使用Exception.ToString() 获取完整的异常文本。发布整个文本。这包括任何内部异常和堆栈跟踪,显示异常被抛出的位置以及导致它的调用链。这将显示这是否是由于证书验证而引发的。
  • 至于其他问题:HttpClient 是线程安全的,意味着可以重用。不这样做会浪费操作系统套接字,从而导致饥饿和崩溃。您只需每次更改request。您应该使用 Encoding.UTF8 而不是每次都创建一个新的 Encoding 实例。那只是浪费时间和内存。如果您已经指定了基地址,则不需要 client.BaseAddress + "/Users? 来创建 URL。 handler.SslProtocols = SslProtocols.Tls12; 阻止您使用 TLS1.3 及更高版本。只需删除此行。 HttpClient 已经尝试使用最新的 TLS 版本。

标签: authentication .net-core ssl-certificate httpclient


【解决方案1】:

我想写评论,但它太大了。所以在这里发布:

对我来说似乎是证书问题。 为了检查这一点,请禁用证书验证:

using (var httpClientHandler = new HttpClientHandler())
{
   httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { return true; };
   using (var client = new HttpClient(httpClientHandler))
   {
   }
}

如果请求有效,您将确定问题出在 SSL 握手上。 不要留下这样的代码!您需要找到根本原因,而不是禁用检查。

如果我的想法是正确的,我的下一个问题是:您的证书是自签名的还是通过受信任的机构颁发的真实证书?

【讨论】:

  • 感谢您的回答。我也尝试了回调,它仍然不适用于 .NET Core。证书是真正的证书,由受信任的机构颁发。
猜你喜欢
  • 1970-01-01
  • 2017-10-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-06
  • 1970-01-01
  • 2019-01-28
  • 1970-01-01
相关资源
最近更新 更多