c# - 由于 SSL 握手异常,.NET Core 3.0 上的 WebRequest 第二次失败

标签 c# ssl .net-core tls1.2 .net-core-3.0

问题是,如果您运行一次下面的代码会成功,但如果您在程序的同一生命周期内运行两次则会失败。

var request = (HttpWebRequest)WebRequest.Create("https://google.com");
var response = (HttpWebResponse)await request.GetResponseAsync();

我有 .NET Core 3.0 SDK 版本 3.0.100 .

复制:
  • dotnet new console -n test-ssl cd test-ssl .
  • 打开Program.cs .
  • 将内容替换为:

  • using System;
    using System.IO;
    using System.Net;
    using System.Threading.Tasks;
    
    namespace test_ssl
    {
        class Program
        {
            static async Task Main(string[] args)
            {
                await CallGoogle();
                await CallGoogle();
            }
    
            private static async Task CallGoogle()
            {
                var request = (HttpWebRequest)WebRequest.Create("https://google.com");
                var response = (HttpWebResponse)await request.GetResponseAsync();
                var jsonResponse = new StreamReader(response.GetResponseStream()).ReadToEnd();
                Console.WriteLine(jsonResponse);
            }
        }
    }
    
  • dotnet run .

  • 这将崩溃,但有以下异常:
    Unhandled exception. System.Net.WebException: The SSL connection could not be established, see inner exception. The handshake failed due to an unexpected packet format.
     ---> System.Net.Http.HttpRequestException: The SSL connection could not be established, see inner exception.
     ---> System.IO.IOException: The handshake failed due to an unexpected packet format.
       at System.Net.Security.SslStream.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)
       at System.Net.Security.SslStream.PartialFrameCallback(AsyncProtocolRequest asyncRequest)
    --- End of stack trace from previous location where exception was thrown ---
       at System.Net.Security.SslStream.ThrowIfExceptional()
       at System.Net.Security.SslStream.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)
       at System.Net.Security.SslStream.EndProcessAuthentication(IAsyncResult result)
       at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)
       at System.Net.Security.SslStream.<>c.<AuthenticateAsClientAsync>b__65_1(IAsyncResult iar)
       at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
    --- End of stack trace from previous location where exception was thrown ---
       at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
       --- End of inner exception stack trace ---
       at System.Net.Http.ConnectHelper.EstablishSslConnectionAsyncCore(Stream stream, SslClientAuthenticationOptions sslOptions, CancellationToken cancellationToken)
       at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean allowHttp2, CancellationToken cancellationToken)
       at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
       at System.Net.Http.HttpConnectionPool.GetHttpConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
       at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
       at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
       at System.Net.Http.HttpClient.FinishSendAsyncUnbuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
       at System.Net.HttpWebRequest.SendRequest()
       at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
       --- End of inner exception stack trace ---
       at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
       at System.Net.WebRequest.<>c.<GetResponseAsync>b__68_2(IAsyncResult iar)
       at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endFunction, Action`1 endAction, Task`1 promise, Boolean requiresSynchronization)
    --- End of stack trace from previous location where exception was thrown ---
       at test_ssl.Program.CallGoogle() in C:\Users\me\source\Workspaces\tests\test-ssl\Program.cs:line 19
       at test_ssl.Program.Main(String[] args) in C:\Users\me\source\Workspaces\tests\test-ssl\Program.cs:line 13
       at test_ssl.Program.<Main>(String[] args)
    

    为什么第二次会失败?

    此问题也发布在 github 上的 .NET Core 中,因为它似乎与此相关:https://github.com/dotnet/core/issues/3847

    进一步测试以缩小问题范围

    .NET Framework 4.8 - 工作

    使用 .NET Framework 4.8 控制台应用程序但是确实有效。所以用原来的Program.cs文件在这里工作。似乎真正的问题在于 .NET Core 3.0

    Docker 中的 .NET Core 3.0 - 工作
    docker run --rm -it mcr.microsoft.com/dotnet/core/sdk:3.0
    dotnet new console -n test-ssl
    cd test-ssl
    // Replace content of Program.cs again.
    dotnet run
    // Everything works.
    

    这让我相信我的机器上有些东西坏了,也许不是防火墙问题,因为最终 docker 容器将通过与我的计算机相同的防火墙到达谷歌。

    Powershell 测试 - 工作

    测试-ssl.ps1
    Invoke-WebRequest -Uri 'https://google.com'
    Invoke-WebRequest -Uri 'https://google.com'
    

    HttpClient .NET Core 3.0 - 不工作

    使用 HttpClient给出同样的错误。所以替换CallGoogle的内容以下不起作用:
    var client = new HttpClient();
    await client.GetStringAsync("https://google.com");
    

    最佳答案

    似乎该系统一定已经以某种方式损坏了,因为它基本上在其他任何地方都可以正常工作。有一台正在工作的新电脑。

    关于c# - 由于 SSL 握手异常,.NET Core 3.0 上的 WebRequest 第二次失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58937402/

    相关文章:

    c# - 延迟加载问题

    c# - 更新后数据集空行

    c# - Azure AD - 验证 token

    java - SSL 证书验证在 Java 中失败 - 但在其他任何地方都有效

    asp.net-core - 从本地文件夹自动更新 nuget 包

    c# - 从 web api 返回 XML 更改字段名称

    mysql - PHP 和 MariaDB : Establish a secure mySQL-Connection

    php - Stripe s2Member Pro 插件在实时模式下返回 card_declined

    c# - 空安全字符串

    .net-core - 方法未找到 : 'System.IServiceProvider Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider'