使用HttpClient,HTTPS请求失败

hcp*_*hcp 22 c# x509certificate2 x509certificate .net-core asp.net-core

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

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.
    }
}
Run Code Online (Sandbox Code Playgroud)

例外:

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()
Run Code Online (Sandbox Code Playgroud)

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

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

更新

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

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

UPDATED2

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

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

handler.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls;
Run Code Online (Sandbox Code Playgroud)

但它还需要以下内容:

handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true;
Run Code Online (Sandbox Code Playgroud)

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

Nei*_*oss 21

根据此SO帖子,您必须使用ServicePointManager启用TLS1.2.

System.Net.ServicePointManager.SecurityProtocol =
    SecurityProtocolType.Tls12 | 
    SecurityProtocolType.Tls11 | 
    SecurityProtocolType.Tls; // comparable to modern browsers
Run Code Online (Sandbox Code Playgroud)

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

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

这表明可能存在某种形式的SHA1块.

  • 需要注意的是,对于.net core 2.0,您需要使用HttpClientHandler而不是ServicePointManager. (6认同)