【发布时间】: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