ฉันจะใช้ 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 ที่ไม่ถูกต้อง คุณสามารถเพิกเฉยต่อปัญหาใบรับรองเหล่านั้นได้หากคุณใส่บรรทัดนี้ก่อนที่คุณจะทำการร้องขอเว็บจริง:

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, chain, ssl) => true;
Charles Ouellet

4
ขอบคุณคุณช่วยฉันด้วย F # ทำให้ง่ายขึ้น:ServicePointManager.ServerCertificateValidationCallback <- Security.RemoteCertificateValidationCallback (fun _ _ _ _ -> true)
David Grenier

2
@Charles Ouellet ฉันคิดว่าฉัน
ขี้เกียจ

24
ฉันชอบ+= delegate { return true; }
vkrzv

2
ตระหนักถึงความเสี่ยงที่อาจเกิดขึ้นจากแนวทางนี้ ดูstackoverflow.com/a/6613434/2969615สำหรับข้อมูลเพิ่มเติม
Joe Coyle

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

ฉันเชื่อว่านี่เป็นการจัดการกับปัญหาอื่น ไม่เกี่ยวกับใบรับรองที่ไม่ถูกต้อง แต่เป็น TLS เวอร์ชันที่สูงกว่า
wp78de

ฉันได้รับ "การเชื่อมต่อที่มีอยู่ถูกบังคับปิดโดยโฮสต์ระยะไกล" และวิธีนี้ใช้ได้ผลสำหรับฉัน
oamilkar

โปรดทราบว่านี่เป็นการกำหนดค่าส่วนกลางดังนั้นคุณต้องทำเพียงครั้งเดียวไม่ใช่ทุกครั้งที่ตั้งค่าคำขอ
Chad Hedgcock

ฉันจะขอเพียงครั้งเดียวได้ไหม ดูเหมือนว่า ServicePointManager จะเป็นสิ่งที่ค่อนข้างเป็นสากล ...
wexman
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.