Làm cách nào để sử dụng WebRequest để truy cập trang web được mã hóa SSL bằng https?


116

Tôi đang viết một chương trình đọc nội dung từ một URL do người dùng cung cấp. Vấn đề của tôi là trong đoạn mã giống như sau:

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

Và điều này sẽ xảy ra nếu url được cung cấp là URL "https: //". Bất cứ ai có thể giúp tôi thay đổi mã này để nó hoạt động với nội dung được mã hóa SSL. Cảm ơn.

Câu trả lời:


175

Bạn đang thực hiện đúng cách nhưng người dùng có thể đang cung cấp url cho các trang web đã cài đặt chứng chỉ SSL không hợp lệ. Bạn có thể bỏ qua những vấn đề chứng chỉ đó nếu bạn đặt dòng này trước khi thực hiện yêu cầu web thực tế:

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

nơi AcceptAllCertificationsđược định nghĩa là

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
Cảm ơn câu trả lời này! Để tránh một số mã vô ích, tôi đã sử dụng nó như sau: ServicePointManager.ServerCertificateValidationCallback = (s, cert, chain, ssl) => true;
Charles Ouellet

4
Cảm ơn, bạn đã giúp tôi thưa ông. F # làm cho điều này trở nên dễ dàng:ServicePointManager.ServerCertificateValidationCallback <- Security.RemoteCertificateValidationCallback (fun _ _ _ _ -> true)
David Grenier

2
@Charles Ouellet Tôi đoán tôi thậm chí lazier hơn bạn, (a, b, c, d) => đúng
Despertar

24
Tôi thích+= delegate { return true; }
vkrzv

2
Nhận thức được những rủi ro tiềm ẩn liên quan đến cách tiếp cận này. Xem stackoverflow.com/a/6613434/2969615 để biết thêm thông tin.
Joe Coyle

19

Liên kết này sẽ được bạn quan tâm: http://msdn.microsoft.com/en-us/library/ds8bxk2a.aspx

Đối với các kết nối http, các lớp WebRequest và WebResponse sử dụng SSL để giao tiếp với các máy chủ web hỗ trợ SSL. Quyết định sử dụng SSL do lớp WebRequest đưa ra, dựa trên URI mà nó được cung cấp. Nếu URI bắt đầu bằng "https:", SSL được sử dụng; nếu URI bắt đầu bằng "http:", kết nối không được mã hóa sẽ được sử dụng.


Liên kết tuyệt vời. Đó là một sự khác biệt quan trọng.
DanM7

1
Câu trả lời của bạn ngụ ý rằng mã trong câu hỏi sẽ hoạt động?
Rowland Shaw

18

Điều này đã làm việc cho tôi:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

1
Giá trị mặc định là "Ssl2 | Tls". Tôi chỉ bật Tls 1.1 và 1.2 trên máy chủ của mình. Điều này thực sự đã khắc phục sự cố! Đối với LetsEncrypt với nginX trên linux, các giao thức được định nghĩa tại đây: /etc/letsencrypt/options-ssl-nginx.conf
Jerther

Tôi tin rằng điều này đang giải quyết một vấn đề khác. Đó không phải là về Chứng chỉ không hợp lệ mà là về các phiên bản TLS cao hơn.
wp78de

Tôi đã nhận được "Kết nối hiện đã buộc phải đóng cửa bởi các máy chủ từ xa" và giải pháp này làm việc cho tôi
oamilkar

Lưu ý rằng đây là cấu hình chung, vì vậy bạn chỉ phải thực hiện việc này một lần và không phải mỗi lần bạn thiết lập yêu cầu.
Chad Hedgcock

Tôi có thể làm điều này cho một yêu cầu duy nhất bằng cách nào đó không? Có vẻ như ServicePointManager là một thứ khá toàn cầu ...
wexman
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.