TLS 1.2 не согласован in.NET 4.7 без явного ServicePointManager.Вызов SecurityProtocol

мне нужно обновить приложение .NET для поддержки вызова API на веб-сайте, который поддерживает только TLS 1.2. Из того, что я читал, если приложение нацелено на 4.6 или выше, по умолчанию оно будет использовать TLS 1.2.

для тестирования я создал приложение Windows Forms, которое нацелено на 4.7. К сожалению, это ошибки, когда я явно не устанавливаю ServicePointManager.SecurityProtocol. Вот код:

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

Если вы раскомментируйте следующую строку:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

это завод. Это не хорошее решение, так как оно жестко кодирует, какую версию TLS использовать, поэтому в будущем он не будет использовать TLS 1.3.

что еще мне нужно сделать, чтобы заставить его работать без этой строки. Я тестирую с машины Window 10 с установленным 4.7.

обновление

я попробовал тест с HttpClient и получил те же результаты, я должен был явно установить SecurityProtocol.

код:

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

4 ответов


начиная с приложений, предназначенных для .NET Framework 4.7, значение по умолчанию ServicePointManager.SecurityProtocol недвижимость SecurityProtocolType.SystemDefault.

это изменение позволяет .NET Framework сетевые API на основе SslStream (например, FTP, HTTPS и SMTP) для наследования протоколов безопасности по умолчанию из операционной системы вместо использования жестко закодированных значений, определенных .NET Framework.

вот причина нового поведения, которое вы испытали, и необходимость новой конфигурации:

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

посмотреть здесь и здесь


Я нашел одно решение. Он не отвечает на вопрос о том, почему TLS 1.2 не используется по умолчанию на Win10 с .NET 4.7, но это позволяет мне не устанавливать ServicePointManager.SecurityProtocol.

решение, что работал от моего 4.5.2 и 4.7 тестирования приложений-добавить приложение.config:

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

здесь все приложения.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>

в качестве альтернативы ответу Ника Y я обнаружил, что в Windows 7 с помощью .NET 4.7+ мне нужно включить эти параметры реестра, чтобы пакет Microsoft Secure Channel (Schannel) правильно отправлял TLS1.1 и TLS1.2.

Это позволяет клиенту .NET продолжать иметь System.Net.ServicePointManager.SecurityProtocol значение SystemDefault и получить TLS 1.1 и 1.2 на компьютере с Windows 7.

[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

Я на Windows 7 и .NET 4.7.1

рекомендации по применению переключатель.Система.Средство servicemodel.DisableUsingServicePointManagerSecurityprotocols и переключатель.Система.Сеть.DontEnableSchUseStrongCrypto упомянутый в двух других ответах не работал в моем проекте, и код OP тоже терпел неудачу.

просмотр исходного кода ServicePointManager и LocalAppContextSwitches я наткнулся на другой конфиг настройка в котором работала.

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