Wie verwende ich WebRequest, um über https auf eine SSL-verschlüsselte Site zuzugreifen?

116

Ich schreibe ein Programm, das Inhalte von einer vom Benutzer angegebenen URL liest. Mein Problem liegt in dem Code, der ungefähr so ​​lautet:

Uri uri = new Uri(url);
WebRequest webRequest = WebRequest.Create(uri);
WebResponse webResponse = webRequest.GetResponse();
ReadFrom(webResponse.GetResponseStream());

Und dies ist fehlerhaft, wenn die angegebene URL eine "https: //" - URL ist. Kann mir jemand helfen, diesen Code so zu ändern, dass er mit SSL-verschlüsselten Inhalten funktioniert? Vielen Dank.

Alfred B. Thordarson
quelle

Antworten:

175

Sie machen es richtig, aber Benutzer geben möglicherweise URLs für Websites an, auf denen ungültige SSL-Zertifikate installiert sind. Sie können diese Zertifizierungsprobleme ignorieren, wenn Sie diese Zeile eingeben, bevor Sie die eigentliche Webanforderung stellen:

ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(AcceptAllCertifications);

wo AcceptAllCertificationsist definiert als

public bool AcceptAllCertifications(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certification, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
    return true;
}
LukeDuff
quelle
41
Danke für diese Antwort! Um nutzlosen Code zu vermeiden, habe ich ihn folgendermaßen verwendet: ServicePointManager.ServerCertificateValidationCallback = (s, cert, chain, ssl) => true;
Charles Ouellet
4
Danke, Sie haben mir geholfen, Sir. F # macht dies so einfacher:ServicePointManager.ServerCertificateValidationCallback <- Security.RemoteCertificateValidationCallback (fun _ _ _ _ -> true)
David Grenier
2
@ Charles Ouellet Ich denke, ich bin noch fauler als Sie, (a, b, c, d) => wahr
Despertar
24
Ich bevorzuge+= delegate { return true; }
vkrzv
2
Seien Sie sich der potenziellen Risiken bewusst, die mit diesem Ansatz verbunden sind. Weitere Informationen finden Sie unter stackoverflow.com/a/6613434/2969615 .
Joe Coyle
19

Dieser Link ist für Sie von Interesse: http://msdn.microsoft.com/en-us/library/ds8bxk2a.aspx

Bei http-Verbindungen verwenden die Klassen WebRequest und WebResponse SSL, um mit Webhosts zu kommunizieren, die SSL unterstützen. Die Entscheidung für die Verwendung von SSL wird von der WebRequest-Klasse basierend auf dem angegebenen URI getroffen. Wenn der URI mit "https:" beginnt, wird SSL verwendet. Wenn der URI mit "http:" beginnt, wird eine unverschlüsselte Verbindung verwendet.

GurdeepS
quelle
Toller Link. Das ist ein wichtiger Unterschied.
DanM7
1
Ihre Antwort impliziert, dass der Code in der Frage funktionieren sollte?
Rowland Shaw
18

Dieser hat für mich gearbeitet:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Nani
quelle
1
Der Standardwert ist "Ssl2 | Tls". Ich hatte nur Tls 1.1 und 1.2 auf meinem Server aktiviert. Dies hat das Problem tatsächlich behoben! Für LetsEncrypt mit nginX unter Linux werden die Protokolle hier definiert: /etc/letsencrypt/options-ssl-nginx.conf
Jerther
Ich glaube, das ist ein anderes Thema. Es geht nicht um ungültige Zertifikate, sondern um höhere TLS-Versionen.
wp78de
Ich bekam "Eine bestehende Verbindung wurde vom Remote-Host zwangsweise geschlossen" und diese Lösung funktionierte für mich
oamilkar
Beachten Sie, dass dies eine globale Konfiguration ist, sodass Sie dies nur einmal und nicht jedes Mal tun müssen, wenn Sie die Anforderung einrichten.
Chad Hedgcock
Kann ich das irgendwie für eine einzelne Anfrage tun? Es scheint, dass ServicePointManager eine ziemlich globale Sache ist ...
wexman