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>