381 Stimmen

Konnte keine Vertrauensbeziehung für den sicheren SSL/TLS-Kanal herstellen - SOAP

Ich habe einen einfachen Webdienstaufruf, der von einer .NET (C#) 2.0 Windows-Anwendung über den von Visual Studio generierten Webdienst-Proxy für einen ebenfalls in C# (2.0) geschriebenen Webdienst generiert wird. Dies hat mehrere Jahre lang funktioniert und tut es auch weiterhin an den etwa ein Dutzend Orten, an denen es ausgeführt wird.

Bei einer Neuinstallation an einem neuen Standort gibt es ein Problem. Beim Versuch, den Webdienst aufzurufen, schlägt er mit der folgenden Meldung fehl:

Es konnte keine Vertrauensbeziehung für die SSL/TLS Secure Kanal

Die URL des Webdienstes verwendet SSL (https://) - aber das funktioniert schon seit langem (und auch weiterhin) von vielen anderen Orten aus.

Wo muss ich suchen? Könnte dies ein Sicherheitsproblem zwischen Windows und .NET sein, das nur bei dieser Installation auftritt? Wenn ja, wo kann ich Vertrauensbeziehungen einrichten? Ich bin ratlos!

408voto

Sebastian Castaldi Punkte 7842

Die folgenden Schnipsel beheben den Fall, dass mit dem SSL-Zertifikat des Servers, den Sie aufrufen, ein Fehler vorliegt. Zum Beispiel kann es selbst signiert sein oder der Hostname zwischen dem Zertifikat und dem Server stimmt nicht überein.

Das ist gefährlich wenn Sie einen Server außerhalb Ihrer direkten Kontrolle anrufen, da Sie nicht mehr so sicher sein können, dass Sie mit dem Server sprechen, mit dem Sie glauben, verbunden zu sein. Wenn Sie jedoch mit internen Servern zu tun haben und die Beschaffung eines "richtigen" Zertifikats nicht praktikabel ist, können Sie dem Webdienst wie folgt mitteilen, dass er die Zertifikatsprobleme ignorieren und tapfer weitermachen soll.

Die ersten beiden verwenden Lambda-Ausdrücke, der dritte verwendet regulären Code. Das erste akzeptiert jedes Zertifikat. Die letzten beiden prüfen zumindest, ob der Hostname im Zertifikat der erwartete ist.
... ich hoffe, Sie finden es hilfreich

//Trust all certificates
System.Net.ServicePointManager.ServerCertificateValidationCallback =
    ((sender, certificate, chain, sslPolicyErrors) => true);

// trust sender
System.Net.ServicePointManager.ServerCertificateValidationCallback
                = ((sender, cert, chain, errors) => cert.Subject.Contains("YourServerName"));

// validate cert by calling a function
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateRemoteCertificate);

// callback used to validate the certificate in an SSL conversation
private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors policyErrors)
{
    bool result = cert.Subject.Contains("YourServerName");
    return result;
}

209voto

Remy Punkte 12219

Die ganz einfache Lösung ist folgende:

System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

Die Lösung von sebastian-castaldi ist etwas ausführlicher.

191voto

Marc Gravell Punkte 970173

Gedanken (aufgrund von Schmerzen in der Vergangenheit):

  • Haben Sie DNS und Sichtverbindung zum Server?
  • Verwenden Sie den richtigen Namen aus dem Zertifikat?
  • Ist das Zertifikat noch gültig?
  • Bringt ein schlecht konfigurierter Load Balancer alles durcheinander?
  • wird die neue Server Maschine die Uhr richtig eingestellt haben (d.h. so, dass die UTC-Zeit korrekt ist [ignorieren Sie die lokale Zeit, sie ist weitgehend irrelevant]) - dies ist sicherlich für WCF von Bedeutung, kann sich also auf reguläres SOAP auswirken?
  • Gibt es ein Problem mit der Vertrauenskette der Zertifikate? Wenn Sie vom Server zum Soap-Dienst browsen, können Sie SSL erhalten?
  • im Zusammenhang mit dem oben Gesagten - wurde das Zertifikat am richtigen Ort installiert? (möglicherweise benötigen Sie eine Kopie in Trusted Root Certification Authorities)
  • Ist der Proxy des Servers auf Maschinenebene richtig eingestellt (anders als der Proxy des Benutzers); siehe proxycfg für XP / 2003 (nicht sicher für Vista usw.)

39voto

cusman Punkte 1661

Mir persönlich gefällt die folgende Lösung am besten:

using System.Security.Cryptography.X509Certificates;
using System.Net.Security;

... dann tun Sie Folgendes, bevor Sie die Fehlermeldung anfordern

System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { return true; };

Dies fand ich nach einer Konsultation Lukes Lösung

23voto

Gregor Slavec Punkte 4714

Wenn Sie nicht jedem blind vertrauen wollen und nur für bestimmte Hosts eine Vertrauensausnahme machen wollen, ist die folgende Lösung besser geeignet.

public static class Ssl
{
    private static readonly string[] TrustedHosts = new[] {
      "host1.domain.com", 
      "host2.domain.com"
    };

    public static void EnableTrustedHosts()
    {
      ServicePointManager.ServerCertificateValidationCallback = 
      (sender, certificate, chain, errors) =>
      {
        if (errors == SslPolicyErrors.None)
        {
          return true;
        }

        var request = sender as HttpWebRequest;
        if (request != null)
        {
          return TrustedHosts.Contains(request.RequestUri.Host);
        }

        return false;
      };
    }
}

Dann rufen Sie einfach Ssl.EnableTrustedHosts auf, wenn Ihre Anwendung startet.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X