Як використовувати WebRequest для доступу до шифрованого SSL-сайту за допомогою https?


116

Я пишу програму, яка читає вміст із наданої користувачем URL-адреси. Моя проблема полягає в коді, який йде приблизно так:

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

І це порушується, якщо наданий URL - це URL-адреса "https: //". Хтось може допомогти мені змінити цей код, щоб він працював із зашифрованим SSL вмістом. Дякую.

Відповіді:


175

Ви робите це правильно, але користувачі можуть надавати URL-адреси на сайти, на яких встановлені недійсні SSL-серти. Ви можете ігнорувати ці проблеми з cert, якщо ви введете цей рядок перед тим, як зробити фактичний веб-запит:

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

де AcceptAllCertificationsвизначено як

public bool AcceptAllCertifications(object sender, System.Security.Cryptography.X509Certificates.X509Certificate certification, System.Security.Cryptography.X509Certificates.X509Chain chain, System.Net.Security.SslPolicyErrors sslPolicyErrors)
{
    return true;
}

41
Дякую за цю відповідь! Щоб уникнути непотрібного коду, я використовував його так: ServicePointManager.ServerCertificateValidationCallback = (s, cert, ланцюг, ssl) => true;
Чарльз Оуеллет,

4
Спасибі, ви допомогли мені, пане. F # робить це так простіше:ServicePointManager.ServerCertificateValidationCallback <- Security.RemoteCertificateValidationCallback (fun _ _ _ _ -> true)
Девід Греньє

2
@Charles Ouellet Я певно, що я навіть лініший за тебе, (a, b, c, d) => правда
Despertar

24
Я віддаю перевагу+= delegate { return true; }
vkrzv

2
Будьте в курсі потенційних ризиків, пов'язаних із цим підходом. Дивіться stackoverflow.com/a/6613434/2969615 для отримання додаткової інформації.
Джо Койл

19

Це посилання буде цікавим для вас: http://msdn.microsoft.com/en-us/library/ds8bxk2a.aspx

Для http-з'єднань класи WebRequest та WebResponse використовують SSL для спілкування з веб-хостами, які підтримують SSL. Рішення про використання SSL приймає клас WebRequest, виходячи з даного URI. Якщо URI починається з "https:", використовується SSL; якщо URI починається з "http:", використовується незашифроване з'єднання.


Чудове посилання. Це важлива відмінність.
DanM7

1
Ваша відповідь означає, що код у питанні повинен працювати?
Rowland Shaw

18

Цей працював на мене:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

1
Значення за замовчуванням - "Ssl2 | Tls". Я тільки ввімкнув Tls 1.1 і 1.2 на своєму сервері. Це справді вирішило проблему! Для LetsEncrypt з nginX на Linux, протоколи визначені тут: /etc/letsencrypt/options-ssl-nginx.conf
Jerther

Я вважаю, що це стосується іншого питання. Йдеться не про недійсні Certs, а про більш високі версії TLS.
wp78de

Я отримував "Існуючий зв'язок був насильно закритий віддаленим хостом", і це рішення працювало для мене
oamilkar

Зауважте, що це глобальна конфігурація, тому робити це потрібно лише один раз, а не кожен раз, коли ви встановлюєте запит.
Чад Хеджкок

Чи можу я це зробити для одного запиту якось? Схоже, що ServicePointManager - досить глобальна річ ...
wexman
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.