Comment utiliser WebRequest pour accéder à un site crypté SSL via https?

116

J'écris un programme qui lit le contenu d'une URL fournie par l'utilisateur. Mon problème est dans le code qui ressemble à ceci:

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

Et c'est cassant si l' URL fournie est une URL "https: //". Quelqu'un peut-il m'aider à modifier ce code afin qu'il fonctionne avec le contenu crypté SSL. Merci.

Alfred B. Thordarson
la source

Réponses:

175

Vous le faites correctement, mais les utilisateurs peuvent fournir des URL à des sites sur lesquels des certificats SSL non valides sont installés. Vous pouvez ignorer ces problèmes de certificat si vous mettez cette ligne avant de faire la requête Web réelle:

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

AcceptAllCertificationsest défini comme

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
la source
41
Merci pour cette réponse! Pour éviter un code inutile, je l'ai utilisé comme ceci: ServicePointManager.ServerCertificateValidationCallback = (s, cert, chain, ssl) => true;
Charles Ouellet
4
Merci, vous m'avez aidé monsieur. F # facilite les choses:ServicePointManager.ServerCertificateValidationCallback <- Security.RemoteCertificateValidationCallback (fun _ _ _ _ -> true)
David Grenier
2
@Charles Ouellet Je suppose que je suis encore plus paresseux que toi, (a, b, c, d) => true
Despertar
24
Je préfère+= delegate { return true; }
vkrzv
2
Soyez conscient des risques potentiels associés à cette approche. Voir stackoverflow.com/a/6613434/2969615 pour plus d'informations.
Joe Coyle
19

Ce lien vous intéressera: http://msdn.microsoft.com/en-us/library/ds8bxk2a.aspx

Pour les connexions http, les classes WebRequest et WebResponse utilisent SSL pour communiquer avec les hôtes Web qui prennent en charge SSL. La décision d'utiliser SSL est prise par la classe WebRequest, en fonction de l'URI qui lui est donné. Si l'URI commence par "https:", SSL est utilisé; si l'URI commence par "http:", une connexion non chiffrée est utilisée.

GurdeepS
la source
Excellent lien. C'est une distinction importante.
DanM7
1
Votre réponse implique que le code de la question devrait fonctionner?
Rowland Shaw le
18

Celui-ci a fonctionné pour moi:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Nani
la source
1
La valeur par défaut est "Ssl2 | Tls". J'avais seulement activé Tls 1.1 et 1.2 sur mon serveur. Cela a en effet résolu le problème! Pour LetsEncrypt avec nginX sous linux, les protocoles sont définis ici: /etc/letsencrypt/options-ssl-nginx.conf
Jerther
Je pense qu'il s'agit d'un problème différent. Il ne s'agit pas de certificats invalides mais de versions TLS supérieures.
wp78de
J'obtenais "Une connexion existante a été fermée de force par l'hôte distant" et cette solution a fonctionné pour moi
oamilkar
Notez qu'il s'agit d'une configuration globale, vous n'avez donc à le faire qu'une seule fois et non à chaque fois que vous configurez la demande.
Chad Hedgcock
Puis-je faire cela pour une seule demande d'une manière ou d'une autre? Il semble que ServicePointManager est une chose plutôt globale ...
wexman