简体   繁体   English

TLS 1.2 未在 .NET 4.7 中协商,没有明确的 ServicePointManager.SecurityProtocol 调用

[英]TLS 1.2 not negotiated in .NET 4.7 without explicit ServicePointManager.SecurityProtocol call

I need to upgrade a .NET application to support a call to an API on a website that only supports TLS 1.2.我需要升级 .NET 应用程序以支持在仅支持 TLS 1.2 的网站上调用 API。 From what I read, if the application is targeting 4.6 or higher then it will use TLS 1.2 by default.据我了解,如果应用程序的目标是 4.6 或更高版本,那么它将默认使用 TLS 1.2。

To test I created a Windows Forms app that targets 4.7.为了测试,我创建了一个针对 4.7 的 Windows Forms 应用程序。 Unfortunately it errors when I don't explicitly set ServicePointManager.SecurityProtocol.不幸的是,当我没有明确设置 ServicePointManager.SecurityProtocol 时它会出错。 Here is the code:这是代码:

HttpClient _client = new HttpClient();

var msg = new StringBuilder();

// If I uncomment the next line it works, but fails even with 4.7
// ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

var httpWebRequest = (HttpWebRequest)WebRequest.Create("https://sandbox.authorize.net");

httpWebRequest.KeepAlive = false;

try
{
    var httpWebResponse = (HttpWebResponse) httpWebRequest.GetResponse();

    msg.AppendLine("The HTTP request Headers for the first request are: ");

    foreach (var header in httpWebRequest.Headers)
    {
        msg.AppendLine(header.ToString());
    }

    ResponseTextBox.Text = msg.ToString();

}
catch (Exception exception)
{
   ResponseTextBox.Text = exception.Message;

   if (exception.InnerException != null)
   {
       ResponseTextBox.Text += Environment.NewLine + @"  ->" + exception.InnerException.Message;

       if (exception.InnerException.InnerException != null)
       {
            ResponseTextBox.Text += Environment.NewLine + @"     ->" + exception.InnerException.InnerException.Message;
       }
   }
}

If you uncomment out the following line:如果您取消注释以下行:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

it works.有用。 This isn't a good solution since it hard codes what TLS version to use, so it wouldn't use TLS 1.3 in future.这不是一个好的解决方案,因为它硬编码了要使用的 TLS 版本,因此将来不会使用 TLS 1.3。

What else do I need to do to get it work without having this line.如果没有这条线,我还需要做什么才能让它工作。 I'm testing from a Window 10 machine with 4.7 installed.我正在从安装了 4.7 的 Window 10 机器上进行测试。

Update更新

I tried a test with HttpClient and had the same results, I had to explicitly set SecurityProtocol.我尝试使用 HttpClient 进行测试并得到相同的结果,我必须显式设置 SecurityProtocol。

Code:代码:

var msg = new StringBuilder();

// Need to uncomment code below for TLS 1.2 to be used
// ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

try
{
   var response = await _client.GetAsync(@"https://sandbox.authorize.net");

   msg.AppendLine("response.IsSuccessStatusCode : " + response.IsSuccessStatusCode);

   msg.AppendLine(await response.Content.ReadAsStringAsync());

   textBox.Text = msg.ToString();
  }

  catch (Exception exception)
  {
      textBox.Text = exception.Message;

      if (exception.InnerException != null)
      {
          textBox.Text += Environment.NewLine + @"  ->" + exception.InnerException.Message;
      }
   }

Starting with apps that target the .NET Framework 4.7, the default value of the ServicePointManager.SecurityProtocol property is SecurityProtocolType.SystemDefault .从面向 .NET Framework 4.7 的应用开始, ServicePointManager.SecurityProtocol属性的默认值为SecurityProtocolType.SystemDefault

This change allows .NET Framework networking APIs based on SslStream (such as FTP, HTTPS, and SMTP) to inherit the default security protocols from the operating system instead of using hard-coded values defined by the .NET Framework.此更改允许基于SslStream 的.NET Framework 网络 API(例如 FTP、HTTPS 和 SMTP)从操作系统继承默认安全协议,而不是使用 .NET Framework 定义的硬编码值。

That's the reason of the new behaviour you experienced and the need of the new configuration:这就是您遇到新行为和需要新配置的原因:

<runtime>
   <AppContextSwitchOverrides value="Switch.System.ServiceModel.DisableUsingServicePointManagerSecurityProtocols=false;Switch.System.Net.DontEnableSchUseStrongCrypto=false" /> 
</runtime>

See here and here看到这里这里

Update (useful info)更新(有用的信息)

Keep in mind, best security practices suggest to update your IIS configuration disabling, time by time, old protocols and ciphers key (eg TLS 1.0, 1.1).请记住,最佳安全实践建议更新禁用 IIS 配置的时间、旧协议和密码密钥(例如 TLS 1.0、1.1)。 See Setup Microsoft Windows or IIS for SSL Perfect Forward Secrecy and TLS 1.2 for very interesting info.有关非常有趣的信息,请参阅为 SSL Perfect Forward Secrecy 和 TLS 1.2 设置 Microsoft Windows 或 IIS

If you follow this practice, you don't need to set the configuration above (as MS suggests), because your Win server / IIS is already well configured.如果您遵循这种做法,则不需要设置上面的配置(如 MS 建议的那样),因为您的 Win 服务器 / IIS 已经配置好了。

Of course, this is possible only if you have access to the server with proper grants.当然,这只有在您获得适当授权才能访问服务器时才有可能。

I had the same issue (Windows 10 and SSL3 / TLS only... not System Default) with a legacy app targeting 4.7.2.我在针对 4.7.2 的旧版应用程序中遇到了同样的问题(仅限 Windows 10 和 SSL3 / TLS ......不是系统默认值)。 My issue was that during the upgrade process over the years we never added in the targetFramework to the system.web > httpRuntime element (Note: it did exist on system.web > compilation element).我的问题是,在多年来的升级过程中,我们从未将targetFramework添加到system.web > httpRuntime元素中(注意:它确实存在于system.web > compilation元素上)。 Before taking bigger steps, ensure your system.web looks something like the following:在采取更大的步骤之前,请确保您的 system.web 类似于以下内容:

<system.web>
    <compilation targetFramework="4.7.2"></compilation>
    <httpRuntime targetFramework="4.7.2" />
</system.web>

In the above example, swap 4.7.2 for whatever version of the framework you are currently using that is >= 4.7.在上面的示例中,将 4.7.2 替换为您当前使用的任何版本的框架 >= 4.7。

As an alternative to Nick Y's answer, I discovered that on Windows 7 using .NET 4.7+, I needed to enable these registry settings in order for the Microsoft Secure Channel (Schannel) package to properly send TLS1.1 and TLS1.2.作为 Nick Y 回答的替代方案,我发现在使用 .NET 4.7+ 的 Windows 7 上,我需要启用这些注册表设置,以便 Microsoft 安全通道 (Schannel) 包正确发送 TLS1.1 和 TLS1.2。

This allows the .NET client to continue to have System.Net.ServicePointManager.SecurityProtocol set to SystemDefault and get TLS 1.1 and 1.2 on a Windows 7 computer.这允许 .NET 客户端继续将System.Net.ServicePointManager.SecurityProtocol设置为SystemDefault并在 Windows 7 计算机上获取 TLS 1.1 和 1.2。

Using the SystemDefault option allows .NET to defer the selection of protocols to the OS.使用SystemDefault选项允许 .NET 将协议的选择推迟到操作系统。 This means that when Microsoft releases hotfixes to the OS to disable insecure protocols or enables support for new ones in their native SCHANNEL library, .NET framework apps running will automatically get this new behavior.这意味着,当 Microsoft 向操作系统发布修补程序以禁用不安全协议或在其本机 SCHANNEL 库中启用对新协议的支持时,运行的 .NET 框架应用程序将自动获得这种新行为。

Here are the registry entries:以下是注册表项:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.1\Client]
"DisabledByDefault"=dword:00000000

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS 1.2\Client]
"DisabledByDefault"=dword:00000000

I've found one solution.我找到了一种解决方案。 It doesn't answer the question about why TLS 1.2 isn't being used by default on Win10 with .NET 4.7, but it does allow me not to have to set ServicePointManager.SecurityProtocol.它没有回答为什么在带有 .NET 4.7 的 Win10 上默认不使用 TLS 1.2 的问题,但它确实让我不必设置 ServicePointManager.SecurityProtocol。

The solution that worked from both my 4.5.2 and 4.7 test apps is to add the following to app.config:适用于我的 4.5.2 和 4.7 测试应用程序的解决方案是将以下内容添加到 app.config:

<AppContextSwitchOverrides value="Switch.System.Net.DontEnableSchUseStrongCrypto=false"/>

Here the whole app.config:这里是整个 app.config:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7"/>
    </startup>
    <runtime>
      <AppContextSwitchOverrides value="Switch.System.Net.DontEnableSchUseStrongCrypto=false"/>
    </runtime>
</configuration>

I am on Windows 7 and .NET 4.7.1我使用的是 Windows 7 和 .NET 4.7.1

The recommendation to use Switch.System.ServiceModel.DisableUsingServicePointManagerSecurityProtocols and Switch.System.Net.DontEnableSchUseStrongCrypto mentioned in two other answers did not work in my project and OP's code was failing too.其他两个答案中提到的使用Switch.System.ServiceModel.DisableUsingServicePointManagerSecurityProtocolsSwitch.System.Net.DontEnableSchUseStrongCrypto的建议在我的项目中不起作用,OP 的代码也失败了。

Reviewing source code for ServicePointManager and LocalAppContextSwitches I came across another config setting which worked.查看ServicePointManagerLocalAppContextSwitches 的源代码时,我发现了另一个有效的配置设置

<runtime>
  <AppContextSwitchOverrides value="Switch.System.Net.DontEnableSystemDefaultTlsVersions=true" />
</runtime>

I had the same problem for a Word VSTO add-in project which initially developed using .NET framework 4.5.2 and then upgraded into 4.7.对于最初使用 .NET 框架 4.5.2 开发然后升级到 4.7 的 Word VSTO 加载项项目,我遇到了同样的问题。 Tried all the solutions in here, but none of them worked for me.尝试了这里的所有解决方案,但没有一个对我有用。 Finally found this article .终于找到这篇文章了。

For those who are having the same problem as me for VSTO add-in projects, add these code in the ThisAddIn.cs class, it worked for me.对于那些在 VSTO 加载项项目中遇到与我相同问题的人,请将这些代码添加到ThisAddIn.cs class 中,它对我有用。

AppContext.SetSwitch("Switch.System.ServiceModel.DisableUsingServicePointManagerSecurityProtocols", false);
AppContext.SetSwitch("Switch.System.Net.DontEnableSchUseStrongCrypto", false);

Windows 7 has TLS1.2 and TLS1.1 disabled by default. Windows 7 默认禁用 TLS1.2 和 TLS1.1。 Enabling it in IE has no effect for other applications.在 IE 中启用它对其他应用程序没有影响。

You should enable it by registry: [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCHANNEL\\Protocols\\TLS 1.2\\Client] "DisabledByDefault"=dword:00000000您应该通过注册表启用它: [HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCHANNEL\\Protocols\\TLS 1.2\\Client] "DisabledByDefault"=dword:00000000

Very useful article with script to set as only TLS1.2 非常有用的文章,脚本设置为仅 TLS1.2

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么要设置 ServicePointManager.SecurityProtocol - why to set ServicePointManager.SecurityProtocol .NET 4.8:评估 Net.ServicePointManager.SecurityProtocol=SystemDefault 到什么? TLS 1.2 问题 - .NET 4.8: What evaluates Net.ServicePointManager.SecurityProtocol=SystemDefault to? TLS 1.2 problems ServicePointManager.SecurityProtocol如何工作? - How does ServicePointManager.SecurityProtocol work? ServicePointManager.SecurityProtocol 不是 SecurityProtocolType.SystemDefault - ServicePointManager.SecurityProtocol is not SecurityProtocolType.SystemDefault 删除/忽略HTTP请求上的ServicePointManager.SecurityProtocol - Remove/ignore ServicePointManager.SecurityProtocol on HTTP requests 即使在指定ServicePointManager.SecurityProtocol之后,HttpWebRequest中的“请求已中止:无法创建SSL / TLS安全通道” - “The request was aborted: Could not create SSL/TLS secure channel” in HttpWebRequest, even after specifying ServicePointManager.SecurityProtocol 使用多个ServicePointManager.SecurityProtocol,首先尝试什么? - Using multiple ServicePointManager.SecurityProtocol, what does it try first? 我们可以向ServicePointManager.SecurityProtocol添加四个协议吗? - Can we add four protocols to ServicePointManager.SecurityProtocol? 为什么ServicePointManager.SecurityProtocol的默认值在不同的计算机上不同? - Why ServicePointManager.SecurityProtocol default value is different on different machines? 使用 .NET Framework 4.7+ 发出 TLS 1.2 请求的问题 - Issues making a TLS 1.2 request with .NET Framework 4.7+
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM