【问题标题】:.NET Core 3.1: Ignore expired SSL certficate.NET Core 3.1:忽略过期的 SSL 证书
【发布时间】:2020-10-29 13:53:07
【问题描述】:

我正在使用 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(请参阅下面的内部异常详细信息)

经过一些研究,我使用了两种方法来解决问题,但问题仍然存在。

方法 1

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
      }
   ]
}

【问题讨论】:

标签: c# ssl .net-core httpclient


【解决方案1】:

快速而肮脏的解决方案

虽然这不是最优雅的解决方案,但一种快速而肮脏的方法就是调用..

这是你要修复你的方法的地方

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;
}

高级解决方案

更好的方法可能是创建一个命名或类型为 HttpClientcustom outgoing handler,这是一个继承自 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);
    }
}

【讨论】:

  • 感谢您的回答,但这两种方法似乎都不起作用。我通过添加整个异常正文来编辑我的帖子。
猜你喜欢
  • 2012-01-31
  • 2017-07-31
  • 2018-05-06
  • 1970-01-01
  • 1970-01-01
  • 2023-04-05
  • 2022-01-17
  • 2023-03-31
  • 1970-01-01
相关资源
最近更新 更多