C# Web 客户端异常:底层连接已关闭:无法为 SSL/TLS 安全通道建立信任关系
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12624841/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Web Client Exception: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel
提问by broke
I have a simple app that uses the C# Web Client class to download a websites HTML. This is a stripped down sample of the code I'm using:
我有一个简单的应用程序,它使用 C# Web Client 类下载网站 HTML。这是我正在使用的代码的精简示例:
WebClient wc = new WebClient();
wc.Headers.Add("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; .NET CLR 1.0.3705;)");
htmlCode = wc.DownloadString("https://www.oig.hhs.gov/exclusions/exclusions_list.asp");
There seems to be an issue with the websites certificate, because I encounter this exception:
网站证书似乎有问题,因为我遇到了这个异常:
The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel." "The remote certificate is invalid according to the validation procedure.
The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel." "The remote certificate is invalid according to the validation procedure.
If you copy and paste the link into a browser, it requires you to agree to the risks before allowing you to view the site. Its a government website, so I'm not worried about any viruses or anything. Is there anyway to tell the web client to bypass this issue, and continue to the site?
如果您将链接复制并粘贴到浏览器中,则需要您同意风险,然后才能允许您查看该网站。它是一个政府网站,所以我不担心任何病毒或任何东西。无论如何要告诉网络客户端绕过这个问题,并继续访问该站点?
采纳答案by Leon Cullens
As far as I know this is because they use a invalid or expired SSL certificate. You can bypass (ignore) it by using:
据我所知,这是因为他们使用了无效或过期的 SSL 证书。您可以使用以下方法绕过(忽略)它:
ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
Edit 2015:
编辑 2015 年:
This post is getting a lot of upvotes, but I regret my answer. It may remove your error, but it won't fix the issue. Accepting any SSL certificates will leave you vulnerable for man in the middle attacks, so it's generally a very bad idea. I will leave this answer for future reference, but please take note that you should try to fix the issue at the root, namely by making sure the SSL certificate is valid.
这篇文章得到了很多赞成,但我对我的回答感到遗憾。它可能会消除您的错误,但不会解决问题。接受任何 SSL 证书将使您容易受到中间人攻击,因此这通常是一个非常糟糕的主意。我会留下这个答案以供将来参考,但请注意,您应该尝试从根本上解决问题,即确保 SSL 证书有效。
回答by Johnny
Try this:
What you would want to do is, to install the certificate into your local machine.
试试这个:
你想要做的是,将证书安装到你的本地机器上。
The procedure if it was notin code would be to do the following:
如果它不在代码中,程序将执行以下操作:
- Open Internet Explorer in Administrator mode (not Chrome).
- Go to the site
- Select proceed
- Click the titelbar / url bar on the certificate, to view the certificate.
- Click install certificate.
- 以管理员模式(不是 Chrome)打开 Internet Explorer。
- 前往网站
- 选择继续
- 点击证书上的titlebar/url栏,查看证书。
- 单击安装证书。
So you can try to have a look at these other questions and see if they help you:
所以你可以试着看看这些其他问题,看看它们是否对你有帮助:
- How can I install a certificate into the local machine store programmatically using c#?
- Install certificates in to the Windows Local user certificate store in C#
Try to install the certificate and see if you go to the url again, if it asks to proceed.
尝试安装证书,看看是否再次访问该 url,如果它要求继续。
****EDIT**:
I read the site certificate, it is because there is a mismatch between the certificate and the site's url.
****编辑**:
我阅读了站点证书,这是因为证书与站点的 url 不匹配。
A simple change would be this:
一个简单的改变是这样的:
htmlCode = wc.DownloadString("https://oig.hhs.gov/exclusions/exclusions_list.asp");
Just remove the www.
只需删除www。
回答by Arvo Bowen
To go even further building off of Leon Cullens' answer I came up with the following. Like he said in his answer, this should not be something you do as a permanent solution but in a case where you are getting this error intentionally this might help you out. This should add a little more security to situations where you do not have a choice and just need it to work.
为了进一步构建 Leon Cullens 的答案,我想出了以下内容。就像他在回答中所说的那样,这不应该是您作为永久解决方案所做的事情,但是在您故意收到此错误的情况下,这可能会帮助您解决问题。这应该为您没有选择而只需要它工作的情况增加一点安全性。
My current situation is during development purposes I needed to use a self signed certificate and not a genuine signed certificate. This of course leads to the following error...
我目前的情况是在开发过程中我需要使用自签名证书而不是真正的签名证书。这当然会导致以下错误......
"The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel."
“底层连接已关闭:无法为 SSL/TLS 安全通道建立信任关系。”
Here is what I did to try and make it just a little more secure and try to avoid the "middle man attacks". I tried to make this as short and simple as possible but wanted to make sure I painted the whole picture to make it easy to understand.
这是我所做的尝试,使其更加安全,并尝试避免“中间人攻击”。我试图让这一切尽可能简短和简单,但我想确保我画了整个画面以使其易于理解。
using System;
using System.Text;
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
namespace TestSecurity
{
class TestDownload
{
private void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
//Progress in the download
}
private void client_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
//Download has completed
}
private bool client_RemoteCertificateValidation(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors == SslPolicyErrors.RemoteCertificateChainErrors)
{
//Check to make sure the domain is correct
X509Certificate2 certificate_details = (X509Certificate2)certificate;
if (certificate_details.Thumbprint == "91A92CA60555DB51BEDDFE1AE4ECE54C8EBEBA97")
{
#region Fingerprint for certificate
string storedFingerprint = "" +
"42048c788db687ed84407da10f78182e3487d1fc31c07ee131151f4e19b360ad2a8c452c2e7d614a5691d5479787fe70dabd" +
"64617465732e626c75656172726f77646576656c6f706d656e742e636f6d3110300e06035504080c0747656f72676961311f" +
"301d060355040a0c16426c7565204172726f7720446576656c6f706d656e74310b3009060355040613025553312f302d0609" +
"2a864886f70d0109011620737570706f727440626c75656172726f77646576656c6f706d656e742e636f6d31123010060355" +
"04070c09436c6576656c616e64301e170d3136303232393231313733335a170d3137303232383231313733335a3081b03129" +
"302706035504030c20757064617465732e626c75656172726f77646576656c6f706d656e742e636f6d3110300e0603550408" +
"42048c788db687ed84407da10f78182e3487d1fc31c07ee131151f4e19b360ad2a8c452c2e7d614a5691d5479787fe70dabd" +
"0613025553312f302d06092a864886f70d0109011620737570706f727440626c75656172726f77646576656c6f706d656e74" +
"2e636f6d3112301006035504070c09436c6576656c616e6430820122300d06092a864886f70d01010105000382010f003082" +
"010a0282010100a1cdf5af6f1bba5cc8495d8061895f39858fde814f5581266505bf4cbe0b26506278bc247963bb7c42f0b8" +
"b00638871932ed7d0a3c6562be8e5b513f24da2768051acde875b53bf94c8ea2cec397145db206b2524c42a2019a0bfa14e2" +
"a7ef0d311235e07b7e0363345fd7f397e365c0865b1b8fa8ad7eebdc1fcdce360db04f2822438621534ae10744155a710641" +
"9a69c16745974a37c5b06917036351b92c06540a6c70aa776c143eef6f7b8ec31c0c40a9eab8a399c9065bea688ea7bd1db2" +
"30af56d2ca0f8983f9e8dacb5613755fbcd8229d7042668a9130468a7480a2afde8c18bab895472ddf1ed2c49291c04e8cc2" +
"ff24db33d231b3a2498c03a5650203010001a34d304b301d0603551d0e0416041476b5c2c82ff138b87c0e2d6c046af4c634" +
"55040a0c16426c75652048c1f54dcb82e3487d1fc31c07ee1313fba9204c7b3232ba9204c7b323a021abcbda85bfca9c9931" +
"092a864886f70d01010b050003820101001ab0dfd318cc2e93a997445d0950ffcb63544c58fe1ded6e234aa7ccdcb5c890b1" +
"61b51ae08c1f54dcb3fbeca9c9932bde91d202b89c0b6f0af1a370017fa9f6a021abcbda85bfecebebc6d6067d4dc1e51ec5" +
"02cf95867516a84f01410cf80d7af4f0d3e9a86cf7b0323dba9204c7b3232c58b2289032a12aaa1ec4f64065da8bbde4fe47" +
"42048c788db687ed84407da10f78182e3487d1fc31c07ee131151f4e19b360ad2a8c452c2e7d614a5691d5479787fe70dabd" +
"de819522bb7ef870595d9738a6acdd39b7fcf6f36948ef2b404c2b6d7ebe577555148ad90013a5c2e812b2b907c808288040" +
"0db6702407585328f7e6c84b40451384391783001174d0";
#endregion
//Use the following to get the server's fingerprint to be saved and compared against
StringBuilder hex = new StringBuilder(certificate_details.RawData.Length * 2);
foreach (byte b in certificate_details.RawData)
hex.AppendFormat("{0:x2}", b);
string serverFingerprint = hex.ToString();
if (serverFingerprint == storedFingerprint) return true;
else return false;
}
else return false;
}
else if (sslPolicyErrors == SslPolicyErrors.None)
return true;
else
return false;
}
public void TestDownload(Uri targetURL, bool useCredentials, string user, string pass)
{
WebClient client = new WebClient();
bool taskCompleted = false;
//Create the event handlers to monitor progress
client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);
client.DownloadDataCompleted += new DownloadDataCompletedEventHandler(client_DownloadDataCompleted);
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(client_RemoteCertificateValidation);
//Resolve the host
IPHostEntry host = Dns.GetHostEntry(targetURL.Host);
IPAddress ip = (host.AddressList.Length > 0 ? host.AddressList[0] : null);
//Show the UI the resolved host
//Account for credentials
if (useCredentials)
{
NetworkCredential credentials = new NetworkCredential(
user,
pass);
client.Credentials = credentials;
}
else client.Credentials = null;
//Download file
client.DownloadDataAsync(targetURL, taskCompleted);
//Go to sleep until the file download has completed
do { Thread.Sleep(500); } while (client.IsBusy);
//File download complete
//Destory the event handlers as they are no longer needed
ServicePointManager.ServerCertificateValidationCallback -= client_RemoteCertificateValidation;
client.DownloadProgressChanged -= client_DownloadProgressChanged;
client.DownloadDataCompleted -= client_DownloadDataCompleted;
}
}
}
回答by Patrick
I had this issue with message:
我有这个消息问题:
Could not establish trust relationship for the SSL/TLS secure channel.
无法为 SSL/TLS 安全通道建立信任关系。
I was connecting to a web service on an Apache server using a .NET client. This is what corrected the problem for me.
我使用 .NET 客户端连接到 Apache 服务器上的 Web 服务。这就是为我解决问题的原因。
(proxy).UserAgent = "Apache-HttpClient/4.1.1 (java 1.5)";
回答by AmirHossein Rezaei
According to this Answer, add this line before using WebClient instance:
根据这个答案,在使用 WebClient 实例之前添加这一行:
ServicePointManager.ServerCertificateValidationCallback = new
RemoteCertificateValidationCallback(delegate { return true; });

