使用HttpClient,HTTPS请求失败

我使用以下代码并获取HttpRequestExceptionexception:

 using (var handler = new HttpClientHandler()) { handler.ClientCertificateOptions = ClientCertificateOption.Manual; handler.SslProtocols = SslProtocols.Tls12; handler.ClientCertificates.Add(new X509Certificate2(@"C:\certificates\cert.pfx")); // I also tried to add another certificates that was provided to https access // by administrators of the site, but it still doesn't work. //handler.ClientCertificates.Add(new X509Certificate2(@"C:\certificates\cert.crt")); //handler.ClientCertificates.Add(new X509Certificate2(@"C:\certificates\cert_ca.crt")); using (var client = new HttpClient(handler)) { var response = client.GetAsync("https://someurl.com/api.php?arg1=some&arg2=test").GetAwaiter().GetResult(); // ^ HttpRequestException: An error occurred while sending the request. } } 

例外:

 WinHttpException: A security error occurred System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult() System.Net.Http.WinHttpHandler+d__105.MoveNext() HttpRequestException: An error occurred while sending the request. System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) System.Runtime.CompilerServices.ConfiguredTaskAwaitable+ConfiguredTaskAwaiter.GetResult() System.Net.Http.HttpClient+d__58.MoveNext() System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) System.Runtime.CompilerServices.TaskAwaiter.GetResult() MyApp.Web.Controllers.HomeController.Test() in HomeController.cs var response = client.GetAsync("https://someurl.com/api.php?arg1=some&arg2=test").GetAwaiter().GetResult(); lambda_method(Closure , object , Object[] ) Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+d__27.MoveNext() 

我还试图将相同的证书导出到Windows证书存储区并通过谷歌浏览器使用它,它工作正常(浏览器要求我确认已安装的证书,然后加载资源)。

为什么它不能在我的代码中工作?

更新

我还尝试添加回调来validation证书:

 handler.ServerCertificateCustomValidationCallback = (message, certificate2, arg3, arg4) => { // I set a breakpoint to this point but it is not catched. return true; }; 

UPDATED2

证书使用SHA-1。 评论中提到Neil Moss 正在撤销对SHA1证书的支持 。 如果它是它无法正常工作的真正原因,是否有解决方法?

谢谢Neil Moss的解决方案。 他建议使用Tls标志进行SSL协议。

 handler.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls; 

但它还需要以下内容:

 handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true; 

我添加这个后它工作正常。

根据此SOpost ,您必须使用ServicePointManager启用TLS1.2。

 System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; // comparable to modern browsers 

另外值得注意的是,ServicePointManager.SecurityProtocols属性的MSDN文档生成了以下语句:

.NET Framework 4.6包含一个新的安全function,可以阻止连接的不安全密码和散列算法。

这表明可能存在某种forms的SHA1块。

这是一份非常有用的文件。 对于ASP.NET Core 2.0,答案应用如下(结果成功):

 using (var handler = new HttpClientHandler()) { handler.ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true; handler.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls; using (HttpClient client = new HttpClient(handler)) { string requestObjJson = requestObj.ToJson(); var address = new Uri($"https://yourcompany.com/"); string token = GetToken(); client.BaseAddress = address; client.DefaultRequestHeaders.Accept.Clear(); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); var contentData = new StringContent(requestObjJson, System.Text.Encoding.UTF8, "application/json"); using (var response = await client.PostAsync("yourcompany/new-employee", contentData)) { var content = response.Content.ReadAsStringAsync(); var taskResult = content.Result; JObject resultObj = JObject.Parse(taskResult); return resultObj; } } }