2017-03-12 491 views
11

我使用下面的代碼,並得到HttpRequestException例外:HTTPS請求失敗使用HttpClient的

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+<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證書存儲和使用它通過谷歌瀏覽器,它工作正常(瀏覽器問我確認安裝的證書,然後加載資源)。

爲什麼它不在我的代碼中工作?

修訂

我還試圖添加回調驗證證書:

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在評論中提到support for SHA1 certs is being withdrawn。 如果這是它不工作的真正原因,是否有解決方法?

SOLUTION

謝謝尼爾·莫斯的解決方案。他建議使用SSL協議的Tls標誌。

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

但還需要以下:

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

後,我加入這一個正常工作。

+2

請詳細說明錯誤:類型,消息和堆棧跟蹤。如果有內部異常,那是什麼? – Richard

+0

嗨@Richard,我用異常消息和堆棧trakces更新了我的問題。 – hcp

+0

需要說明的是,您是否試圖通過_client certificate_通過HTTPS進行連接,或者您是否試圖包含自簽名的_server證書_,您希望將其視爲有效? –

回答

12

根據this SO post,您必須使用ServicePointManager啓用TLS1.2。

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

同樣值得注意的是,在MSDN documentation爲ServicePointManager.SecurityProtocols屬性使得這樣的說法:

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

這表明某種形式的SHA1塊的可能到位。

+1

非常感謝Neil Moss!我添加了Tls協議後,它可以工作!但據我所知沒有'System.Net.ServicePointManager.SecurityProtocol',但我用'handler.SslProtocols = SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls;' – hcp

+0

需要注意的是,對於.net核心2.0,您將需要使用HttpClientHandler而不是ServicePointManager。 –

相關問題