HTTPS 请求使用 HttpClient 失败 [英] HTTPS request fails using HttpClient

查看:63
本文介绍了HTTPS 请求使用 HttpClient 失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用以下代码并获得 HttpRequestException 异常:

I am using the following code and get HttpRequestException exception:

using (var handler = new HttpClientHandler())
{
    handler.ClientCertificateOptions = ClientCertificateOption.Manual;
    handler.SslProtocols = SslProtocols.Tls12;
    handler.ClientCertificates.Add(new X509Certificate2(@"C:certificatescert.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:certificatescert.crt"));
    //handler.ClientCertificates.Add(new X509Certificate2(@"C:certificatescert_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+<StartRequest>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+<FinishSendAsync>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+<InvokeActionMethodAsync>d__27.MoveNext()

我还尝试将相同的证书导出到 Windows 证书存储并通过 Google Chrome 使用它,并且运行良好(浏览器要求我确认已安装的证书,然后加载资源).​​

I also tried to export the same certificates to Windows Certificate Store and use it via Google Chrome and it works fine (browser asked me to confirm installed certificate and then loaded the resource).

为什么它在我的代码中不起作用?

Why it's not working in my code?

更新

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

I also tried to add callback to validate the certificate:

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 证书撤回.如果这是它不工作的真正原因,是否有解决方法?

The certificate is used SHA-1. Neil Moss is mentioned in the comments that support for SHA1 certs is being withdrawn. If it is the real reason why it is not working, is there workaround for it?

解决方案

感谢 Neil Moss 的解决方案.他建议对 SSL 协议使用 Tls 标志.

Thank you Neil Moss for solution. He proposed to use Tls flag for SSL protocol.

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

但它还需要以下内容:

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

在我添加这个之后,它工作正常.

After I added this one it works fine.

推荐答案

根据这个 SO 帖子,您必须启用带有 ServicePointManager 的 TLS1.2.

According to this SO post, you must enable TLS1.2 with ServicePointManager.

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

同样值得注意的是,MSDN 文档 做出了以下声明:

Also noteworthy, the MSDN documentation for ServicePointManager.SecurityProtocols property makes this statement:

.NET Framework 4.6 包含一项新的安全功能,可阻止用于连接的不安全密码和哈希算法.

The .NET Framework 4.6 includes a new security feature that blocks insecure cipher and hashing algorithms for connections.

这表明某种形式的 SHA1 块可能到位.

which suggests that some form of SHA1 block might be in place.

编辑 2020 年 9 月 16 日

EDIT 16 Sep 2020

我从 = 赋值运算符更改为 |= 运算符,以便对任何其他仍需要 SSL 的旧站点的请求将继续有效.

I changed from the = assignment operator to the |= operator so that requests to any other legacy sites which still require SSL will continue to work.

这篇关于HTTPS 请求使用 HttpClient 失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆