webentwicklung-frage-antwort-db.com.de

TLS 1.2 wurde in .NET 4.7 ohne expliziten ServicePointManager.SecurityProtocol-Aufruf nicht ausgehandelt

Ich muss eine .NET-Anwendung aktualisieren, um einen Aufruf einer API auf einer Website zu unterstützen, die nur TLS 1.2 unterstützt. Soweit ich weiß, verwendet die Anwendung standardmäßig TLS 1.2, wenn sie auf 4.6 oder höher abzielt.

Zum Testen habe ich eine Windows Forms-App erstellt, die auf 4.7 abzielt. Leider tritt ein Fehler auf, wenn ich ServicePointManager.SecurityProtocol nicht explizit einstelle. Hier ist der 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;
       }
   }
}

Wenn Sie die folgende Zeile auskommentieren:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

es klappt. Dies ist keine gute Lösung, da es festlegt, welche TLS-Version verwendet werden soll, sodass TLS 1.3 in Zukunft nicht mehr verwendet wird.

Was muss ich noch tun, damit es funktioniert, ohne diese Zeile zu haben? Ich teste von einem Windows 10-Computer mit 4.7.

pdate

Ich habe einen Test mit HttpClient versucht und hatte die gleichen Ergebnisse, ich musste SecurityProtocol explizit einstellen.

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

Ich habe eine Lösung gefunden. Es beantwortet nicht die Frage, warum TLS 1.2 unter Win10 mit .NET 4.7 nicht standardmäßig verwendet wird, aber es ermöglicht mir, dass ich ServicePointManager.SecurityProtocol nicht festlegen muss.

Die Lösung, die sowohl mit meinen 4.5.2- als auch 4.7-Test-Apps funktioniert hat, besteht darin, app.config Folgendes hinzuzufügen:

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

Hier die ganze 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>
6
Josh

Beginnend mit Anwendungen, die auf .NET Framework 4.7 abzielen, lautet der Standardwert der Eigenschaft ServicePointManager.SecurityProtocol SecurityProtocolType. SystemDefault .

Durch diese Änderung können .NET Framework-Netzwerk-APIs, die auf SslStream basieren (z. B. FTP, HTTPS und SMTP), stattdessen die Standardsicherheitsprotokolle vom Betriebssystem erben der Verwendung von fest codierten Werten, die von .NET Framework definiert wurden.

Das ist der Grund für das neue Verhalten und die Notwendigkeit der neuen Konfiguration:

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

Siehe hier und hier

14

Als Alternative zu Nick Ys Antwort stellte ich fest, dass ich unter Windows 7 mit .NET 4.7+ diese Registrierungseinstellungen aktivieren musste, damit das Microsoft Secure Channel-Paket (Schannel) TLS1.1 und TLS1.2 ordnungsgemäß senden konnte.

Dadurch kann der .NET-Client weiterhin System.Net.ServicePointManager.SecurityProtocol Auf SystemDefault setzen und TLS 1.1 und 1.2 auf einem Windows 7-Computer herunterladen.

Mit der Option SystemDefault kann .NET die Auswahl der Protokolle auf das Betriebssystem verschieben. Dies bedeutet, dass .NET Framework-Apps, die ausgeführt werden, dieses neue Verhalten automatisch erhalten, wenn Microsoft Hotfixes für das Betriebssystem veröffentlicht, um unsichere Protokolle zu deaktivieren oder die Unterstützung für neue Protokolle in ihrer systemeigenen SCHANNEL-Bibliothek zu aktivieren.

Hier sind die Registrierungseinträge:

[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
7
MerickOWA

Ich arbeite unter Windows 7 und .NET 4.7.1

Die Empfehlung zur Verwendung von Switch.System.ServiceModel.DisableUsingServicePointManagerSecurityProtocols und Switch.System.Net.DontEnableSchUseStrongCrypto , das in zwei anderen Antworten erwähnt wurde, funktionierte in meinem Projekt nicht und der OP-Code schlug ebenfalls fehl.

Überprüfen des Quellcodes für ServicePointManager und LocalAppContextSwitches Ich bin auf einen anderen gestoßen config Einstellung was hat funktioniert.

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

Ich hatte das gleiche Problem (nur Windows 10 und SSL3/TLS ... nicht Systemstandard) mit einer älteren App, die auf 4.7.2 abzielt. Mein Problem war, dass wir während des Upgrade-Prozesses im Laufe der Jahre dem system.web> targetFramework -Element niemals das httpRuntime _ hinzugefügt haben (Hinweis: Es war in system.web> vorhanden) compilation Element). Stellen Sie vor größeren Schritten sicher, dass Ihr system.web wie folgt aussieht:

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

Tauschen Sie im obigen Beispiel 4.7.2 gegen die Version des Frameworks aus, die Sie gerade verwenden, dh> = 4.7.

4
scottheckel