簡體   English   中英

.NET Core 3.1:忽略過期的 SSL 證書

[英].NET Core 3.1: Ignore expired SSL certficate

我正在使用 HttpClient (.NET Core3.1) 從多個來源獲取請求。 我在構造函數中只使用了一個實例,如下所示:

_httpClient = new HttpClient();

_httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));
_httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("covid19App", "2.0"));

get調用方法如下:

private HttpResponseMessage Get(string url)
{
    var response = _httpClient.GetAsync(url).Result;

    int count = 0;

    while (count < 3 && response.IsSuccessStatusCode)
    {
        response = _httpClient.GetAsync(url).Result;
        count++;

    }

    return response;

}

在我的 SSL 證書過期之前,我對上述邏輯沒有任何問題。 現在對其中一個源的調用返回異常The SSL connection could not be established, see inner exception (有關內部異常詳細信息,請參見下文)

經過一番研究,我使用了兩種方法來解決問題,但問題仍然存在。

方法一

var handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = (sender, certificate, chain, errors) => true;

_httpClient = new HttpClient(handler);

方法二:

ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, sslPolicyErrors) => true;

_httpClient = new HttpClient();

_httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));
_httpClient.DefaultRequestHeaders.UserAgent.Add(new ProductInfoHeaderValue("covid19App", "2.0"));

那么有沒有其他方法可以解決這個問題?

內部異常: The SSL connection could not be established, see inner exception. => Authentication failed, see inner exception => The message received was unexpected or badly formatted.

編輯:添加了整個異常主體

{
   "ClassName":"System.AggregateException",
   "Message":"One or more errors occurred.",
   "Data":null,
   "InnerException":{
      "StackTrace":"   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)\r\n   at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean allowHttp2, CancellationToken cancellationToken)\r\n   at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n   at System.Net.Http.HttpConnectionPool.GetHttpConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n   at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)\r\n   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n   at Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n   at Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n   at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)",
      "Message":"The SSL connection could not be established, see inner exception.",
      "Data":{
         
      },
      "InnerException":{
         "ClassName":"System.Security.Authentication.AuthenticationException",
         "Message":"Authentication failed, see inner exception.",
         "Data":null,
         "InnerException":{
            "ClassName":"System.ComponentModel.Win32Exception",
            "Message":"The message received was unexpected or badly formatted.",
            "Data":null,
            "InnerException":null,
            "HelpURL":null,
            "StackTraceString":null,
            "RemoteStackTraceString":null,
            "RemoteStackIndex":0,
            "ExceptionMethod":null,
            "HResult":-2147467259,
            "Source":null,
            "WatsonBuckets":null,
            "NativeErrorCode":-2146893018
         },
         "HelpURL":null,
         "StackTraceString":"   at System.Net.Security.SslStream.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception)\r\n   at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)\r\n   at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)\r\n   at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)\r\n   at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)\r\n   at System.Net.Security.SslStream.PartialFrameCallback(AsyncProtocolRequest asyncRequest)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Net.Security.SslStream.ThrowIfExceptional()\r\n   at System.Net.Security.SslStream.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)\r\n   at System.Net.Security.SslStream.EndProcessAuthentication(IAsyncResult result)\r\n   at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)\r\n   at System.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__65_1(IAsyncResult iar)\r\n   at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)",
         "RemoteStackTraceString":null,
         "RemoteStackIndex":0,
         "ExceptionMethod":null,
         "HResult":-2146233087,
         "Source":"System.Private.CoreLib",
         "WatsonBuckets":null
      },
      "HelpLink":null,
      "Source":"System.Net.Http",
      "HResult":-2146233087
   },
   "HelpURL":null,
   "StackTraceString":"   at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)\r\n   at System.Threading.Tasks.Task`1.GetResultCore(Boolean waitCompletionNotification)\r\n   at System.Threading.Tasks.Task`1.get_Result()\r\n   at Covid19.DataService.RawData.RawDataImportService.Get(String url) in E:\\Covid19\\Backend\\Covid19\\Covid19.DataService\\RawData\\RawDataImportService.cs:line 346\r\n   at Covid19.DataService.RawData.RawDataImportService.ImportECDPCData(DataSource source, IDictionary`2 populations, IEnumerable`1& locations, List`1& log) in E:\\Covid19\\Backend\\Covid19\\Covid19.DataService\\RawData\\RawDataImportService.cs:line 60\r\n   at Covid19.DataService.RawData.RawDataImportService.ImportData(DataSource source, IDictionary`2 populations, IEnumerable`1& locations, List`1& log) in E:\\Covid19\\Backend\\Covid19\\Covid19.DataService\\RawData\\RawDataImportService.cs:line 40",
   "RemoteStackTraceString":null,
   "RemoteStackIndex":0,
   "ExceptionMethod":null,
   "HResult":-2146233088,
   "Source":"System.Private.CoreLib",
   "WatsonBuckets":null,
   "InnerExceptions":[
      {
         "StackTrace":"   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)\r\n   at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean allowHttp2, CancellationToken cancellationToken)\r\n   at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n   at System.Net.Http.HttpConnectionPool.GetHttpConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n   at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)\r\n   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n   at Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n   at Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)\r\n   at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)",
         "Message":"The SSL connection could not be established, see inner exception.",
         "Data":{
            
         },
         "InnerException":{
            "ClassName":"System.Security.Authentication.AuthenticationException",
            "Message":"Authentication failed, see inner exception.",
            "Data":null,
            "InnerException":{
               "ClassName":"System.ComponentModel.Win32Exception",
               "Message":"The message received was unexpected or badly formatted.",
               "Data":null,
               "InnerException":null,
               "HelpURL":null,
               "StackTraceString":null,
               "RemoteStackTraceString":null,
               "RemoteStackIndex":0,
               "ExceptionMethod":null,
               "HResult":-2147467259,
               "Source":null,
               "WatsonBuckets":null,
               "NativeErrorCode":-2146893018
            },
            "HelpURL":null,
            "StackTraceString":"   at System.Net.Security.SslStream.StartSendAuthResetSignal(ProtocolToken message, AsyncProtocolRequest asyncRequest, ExceptionDispatchInfo exception)\r\n   at System.Net.Security.SslStream.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)\r\n   at System.Net.Security.SslStream.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)\r\n   at System.Net.Security.SslStream.ProcessReceivedBlob(Byte[] buffer, Int32 count, AsyncProtocolRequest asyncRequest)\r\n   at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)\r\n   at System.Net.Security.SslStream.PartialFrameCallback(AsyncProtocolRequest asyncRequest)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Net.Security.SslStream.ThrowIfExceptional()\r\n   at System.Net.Security.SslStream.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)\r\n   at System.Net.Security.SslStream.EndProcessAuthentication(IAsyncResult result)\r\n   at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)\r\n   at System.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__65_1(IAsyncResult iar)\r\n   at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)",
            "RemoteStackTraceString":null,
            "RemoteStackIndex":0,
            "ExceptionMethod":null,
            "HResult":-2146233087,
            "Source":"System.Private.CoreLib",
            "WatsonBuckets":null
         },
         "HelpLink":null,
         "Source":"System.Net.Http",
         "HResult":-2146233087
      }
   ]
}

快速而骯臟的解決方案

雖然這不是最優雅的解決方案,但一種快速而骯臟的方法是調用..

這是您將修復您的方法的地方

private HttpResponseMessage Get(string url)
{
    // HACK: set the policy here
    ServicePointManager.ServerCertificateValidationCallback +=
        (sender, cert, chain, sslPolicyErrors) => true; 

    // note:
    // also might be worth taking a look at DangerousAcceptAnyServerCertificateValidator

    var response = _httpClient.GetAsync(url).Result;

    int count = 0;

    while (count < 3 && response.IsSuccessStatusCode)
    {
        response = _httpClient.GetAsync(url).Result;
        count++;

    }

    return response;
}

先進的解決方案

更好的方法可能是使用自定義傳出處理程序創建命名或類型化的HttpClient ,該處理程序是從DelegatingHandler繼承的類。

例如

public class IgnoreSSLValidateDelegatingHandler : DelegatingHandler
{
    // this commented block could be useful if you want to allow a defined
    // group of certicates, rather than just anything out in the wild.
    // -------------------------------------------------------------------
    //private readonly X509CertificateCollection _certificates;
    //public IgnoreSSLValidateDelegatingHandler()
    //{
    //  _certificates = new X509CertificateCollection();
    //}

    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request,
        System.Threading.CancellationToken cancellationToken)
    {
        HttpMessageHandler handler = this.InnerHandler;

        while (handler is DelegatingHandler)
        {
            handler = ((DelegatingHandler)handler).InnerHandler;
        }

        if (handler is HttpClientHandler httpClientHandler
            && httpClientHandler.ServerCertificateCustomValidationCallback == null)
        {
            httpClientHandler
                .ServerCertificateCustomValidationCallback =
                    (message, cert, chain, errors) => true;
        }
        
        return base.SendAsync(request, cancellationToken);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM