43 Stimmen

Wie man einen Zertifikatsfehler mit c# 2.0 WebClient ignoriert - ohne Zertifikat

Verwendung von Visual Studio 2005 - C# 2.0, System.Net.WebClient.UploadData(Uri address, byte[] data) Windows Server 2003

Hier ist also eine abgespeckte Version des Codes:

static string SO_method(String fullRequestString)
{
    string theUriStringToUse = @"https://10.10.10.10:443"; // populated with real endpoint IP:port
    string proxyAddressAndPort = @"http://10.10.10.10:80/"; // populated with a real proxy IP:port
    Byte[] utf8EncodedResponse; // for the return data in utf8
    string responseString; // for the return data in utf16

    WebClient myWebClient = new WebClient(); // instantiate a web client
    WebProxy proxyObject = new WebProxy(proxyAddressAndPort, true);// instantiate & popuylate a web proxy
    myWebClient.Proxy = proxyObject; // add the proxy to the client
    myWebClient.Headers.Add("Content-Type", "application/x-www-form-urlencoded"); // stick some stuff in the header

    UTF8Encoding utf8Encoding = new UTF8Encoding(false);// create a utf8 encoding
    Byte[] utf8EncodedRequest = HttpUtility.UrlEncodeToBytes(fullRequestString, utf8Encoding); // convert the request data to a utf8 byte array

    try
    {
        utf8EncodedResponse = myWebClient.UploadData(theUriStringToUse, "POST", utf8EncodedRequest); // pass the utf8-encoded byte array
        responseString = utf8Encoding.GetString(utf8EncodedResponse); // get a useable string out of the response
    }
    catch (Exception e)
    {
        // some other error handling
        responseString = "<CommError><![CDATA[" + e.ToString() + "]]></CommError>";// show the basics of the problem
    }
    return responseString;// return whatever ya got
}

Ich erhalte folgende Fehlermeldung:

Die zugrunde liegende Verbindung wurde geschlossen: Es konnte keine Vertrauensbeziehung für den sicheren SSL/TLS-Kanal hergestellt werden.

Ich habe nicht viel Kontrolle, um zu sehen, was passiert, wenn die Anfrage rausgeht. Mir wird gesagt, dass sie das richtige Ziel erreicht und ein "Zertifikatsfehler" vorliegt. Das liegt angeblich daran, dass die IP-Adresse in meiner Anfrage und die URL, zu der sie aufgelöst wird, nicht übereinstimmen. Ich habe mehr als eine IP-Adresse, zu der ich Round-Robin durchführen soll, so dass die Angabe der URL nicht funktioniert. Ich hänge kein Zertifikat an - und das soll ich laut den Endpunkteigentümern auch nicht tun. Laut "ihnen" ist der Zertifikatsfehler "normal und ich soll ihn ignorieren.

Das fragliche Zertifikat ist angeblich eines der vielen Verisign-Zertifikate, die auf unserem Server "einfach da" sind. Die Beispiele, die ich für das Ignorieren von Zertifikatsfehlern gesehen habe, scheinen alle zu implizieren, dass der Anfragende ein bestimmtes x509-Zertifikat anhängt (was ich nicht tue).

Ich sah hinüber .net WebService, ssl-Validierung umgehen! was irgendwie mein Problem beschreibt - nur irgendwie auch nicht, weil ich nicht weiß, auf welches Zertifikat (wenn überhaupt) ich mich beziehen soll.

Gibt es eine Möglichkeit, den Fehler zu ignorieren, ohne zu wissen, welches Zertifikat das Problem verursacht?

  • und bitte - Samthandschuhe, kleine Worte und "für Dummies"-Code, denn ich bin nicht gerade ein harter Brocken.

  • Dieser Datenverkehr läuft über eine private Leitung - ich gehe also davon aus, dass das Ignorieren des Zertifizierungsfehlers nicht so schlimm ist, wie wenn es sich um offenen Internetverkehr handelt.

63voto

MattH Punkte 3967

Das SSL-Zertifikat dient dazu, dass ein Rechner eine Vertrauensbeziehung aufbauen kann. Wenn Sie eine IP-Adresse eingeben und am Ende mit einer anderen sprechen, klingt das nach einem DNS-Hijack-Sicherheitsfehler, der mit SSL vermieden werden soll - und den Sie sich vielleicht nicht von "denen" gefallen lassen wollen.

Wenn Sie am Ende mit mehr als einem Rechner sprechen (im Idealfall lassen sie es für Sie als einen erscheinen), benötigen Sie für jeden der möglichen Rechner ein Zertifikat, um Vertrauen zu schaffen.

Um das Vertrauen zu ignorieren (ich musste dies bisher nur vorübergehend in Entwicklungsszenarien tun), kann das folgende Snippet für Sie funktionieren, aber ich empfehle Ihnen dringend, die Auswirkungen des Ignorierens des Vertrauens zu bedenken, bevor Sie es verwenden:

public static void InitiateSSLTrust()
{
    try
    {
        //Change SSL checks so that all checks pass
        ServicePointManager.ServerCertificateValidationCallback =
           new RemoteCertificateValidationCallback(
                delegate
                { return true; }
            );
    }
    catch (Exception ex)
    {
        ActivityLog.InsertSyncActivity(ex);
    }
}

24voto

Adam Plocher Punkte 13633

Ich weiß, dass dies ein alter Beitrag ist, aber ich wollte nur zeigen, dass es einen kürzeren Weg gibt, dies zu tun (mit .NET 3.5+ und später).

Vielleicht ist es nur meine Zwangsneurose, aber ich wollte diesen Code so weit wie möglich minimieren. Dies scheint der kürzeste Weg zu sein, es zu tun, aber ich habe auch einige längere Äquivalente unten aufgeführt:

// 79 Characters (72 without spaces)
ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => true;

Kürzester Weg in .NET 2.0 (das ist das, wonach die Frage speziell gerichtet war)

// 84 Characters
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

Es ist bedauerlich, dass man bei der Lambda-Methode die Parameter definieren muss, sonst könnte es noch kürzer sein.

Und für den Fall, dass Sie einen viel längeren Weg benötigen, finden Sie hier einige weitere Alternativen:

ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, errors) => true;

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

// 255 characters - lots of code!
ServicePointManager.ServerCertificateValidationCallback =
    new RemoteCertificateValidationCallback(
        delegate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            return true;
        });

12voto

Jaxidian Punkte 12585

Dies ist etwas der Code, den wir verwenden (noch nicht poliert - ich glaube nicht, dass ich die Fehlerbehandlung-Setup richtig, aber es sollte in der Nähe sein), basierend auf thomas Vorschlag (dies ist .NET 4.0-Code, obwohl):

var sslFailureCallback = new RemoteCertificateValidationCallback(delegate { return true; });

try
{

    if (ignoreSslErrors)
    {
        ServicePointManager.ServerCertificateValidationCallback += sslFailureCallback;
    }

    response = webClient.UploadData(Options.Address, "POST", Encoding.ASCII.GetBytes(Options.PostData));

}
catch (Exception err)
{
    PageSource = "POST Failed:\r\n\r\n" + err;
    return PageSource;
}
finally
{
    if (ignoreSslErrors)
    {
        ServicePointManager.ServerCertificateValidationCallback -= sslFailureCallback;
    }
}

8voto

thomas Punkte 81

Dieser Kodex ist viel umfassender, als Sie vielleicht erwarten. Er ist prozessübergreifend. Der Prozess kann die Exe, IIS auf diesem Rechner oder sogar DLLHost.exe sein. Nach dem Aufruf sollten Sie einen finally-Block einfügen, der den normalen Zustand wiederherstellt, indem Sie den Delegaten entfernen, der immer true zurückgibt.

4voto

Jürgen Steinblock Punkte 28819

Ich wollte die SSL-Prüfung für eine bestimmte Domain deaktivieren, ohne sie global zu deaktivieren, weil möglicherweise andere Anfragen laufen, die nicht betroffen sein sollten, also kam ich auf diese Lösung (bitte beachten Sie, dass uri eine Variable innerhalb einer Klasse ist:

        private byte[] UploadValues(string method, NameValueCollection data)
        {
            var client = new WebClient();

            try
            {
                ServicePointManager.ServerCertificateValidationCallback +=
                    ServerCertificateValidation;

                returnrclient.UploadValues(uri, method, parameters);

            }
            finally
            {
                ServicePointManager.ServerCertificateValidationCallback -=
                    ServerCertificateValidation;
            }
        }

        private bool ServerCertificateValidation(object sender,
            X509Certificate certificate, X509Chain chain,
            SslPolicyErrors sslPolicyErrors)
        {
            var request = sender as HttpWebRequest;
            if (request != null && request.Address.Host.Equals(
                this.uri.Host, StringComparison.OrdinalIgnoreCase))
                return true;
            return false;
        }

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