如何使用 c# 2.0 WebClient 忽略证书错误 - 没有证书

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1301127/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 14:53:37  来源:igfitidea点击:

How to ignore a certificate error with c# 2.0 WebClient - without the certificate

c#ssl-certificatewebclient

提问by

Using Visual Studio 2005 - C# 2.0, System.Net.WebClient.UploadData(Uri address, byte[] data)Windows Server 2003

使用 Visual Studio 2005 - C# 2.0、System.Net.WebClient.UploadData(Uri address, byte[] data)Windows Server 2003

So here's a stripped down version of the code:

所以这是代码的精简版本:

static string SO_method(String fullRequestString)
{
    string theUriStringToUse = @"https://10.10.10.10:443"; // populated with real endpoint IP:port
    string proxyAddressAndPort = @"http://10.10.10.10:80/"; // populated with a real proxy IP:port
    Byte[] utf8EncodedResponse; // for the return data in utf8
    string responseString; // for the return data in utf16

    WebClient myWebClient = new WebClient(); // instantiate a web client
    WebProxy proxyObject = new WebProxy(proxyAddressAndPort, true);// instantiate & popuylate a web proxy
    myWebClient.Proxy = proxyObject; // add the proxy to the client
    myWebClient.Headers.Add("Content-Type", "application/x-www-form-urlencoded"); // stick some stuff in the header

    UTF8Encoding utf8Encoding = new UTF8Encoding(false);// create a utf8 encoding
    Byte[] utf8EncodedRequest = HttpUtility.UrlEncodeToBytes(fullRequestString, utf8Encoding); // convert the request data to a utf8 byte array

    try
    {
        utf8EncodedResponse = myWebClient.UploadData(theUriStringToUse, "POST", utf8EncodedRequest); // pass the utf8-encoded byte array
        responseString = utf8Encoding.GetString(utf8EncodedResponse); // get a useable string out of the response
    }
    catch (Exception e)
    {
        // some other error handling
        responseString = "<CommError><![CDATA[" + e.ToString() + "]]></CommError>";// show the basics of the problem
    }
    return responseString;// return whatever ya got
}

This is the error I get:

这是我得到的错误:

The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.

底层连接已关闭:无法为 SSL/TLS 安全通道建立信任关系。

I don't have much control to see what's happening when the request goes out. I'm told that it's reaching the correct destination and there's a "certificate error". This is supposedly because there's a literal mismatch between the IP address in my request and the URL it resolves to. I have more than one IP I'm supposed to round-robin to so specifying the URL won't work. I'm not attaching a certificate - nor am I supposed to according to the endpoint owners. Per "them" the certificate error is 'normal and I am supposed to ignore it.

我没有太多控制权来查看请求发出时发生了什么。我被告知它正在到达正确的目的地,并且出现“证书错误”。这可能是因为我的请求中的 IP 地址与其解析到的 URL 之间存在字面不匹配。我有多个 IP 我应该循环使用,因此指定 URL 将不起作用。我没有附上证书 - 根据端点所有者的说法,我也不应该附上证书。根据“他们”,证书错误是“正常的,我应该忽略它”。

The cert in question is supposedly one of the many verisign certs that is "just there" on our server. The examples I've seen for ignoring cert errors all seem to imply that the requestor is attaching a specific x509 certificate (which I'm not).

有问题的证书应该是我们服务器上“就在那里”的众多 verisign 证书之一。我看到的忽略证书错误的示例似乎都暗示请求者附加了特定的 x509 证书(我不是)。

I looked over .net WebService, bypass ssl validation!which kinda-sorta describes my problem - except it also kinda-sorta doesn't because I don't know which certificate (if any) I should reference.

我查看了.net WebService,绕过了 ssl 验证!which kinda-sorta 描述了我的问题 - 除了它也有点-sorta 没有,因为我不知道我应该参考哪个证书(如果有)。

Is there a way for me to ignore the error without actually knowing/caring what certificate is causing the problem?

有没有办法让我忽略错误而不实际知道/关心导致问题的证书?

  • and please - kid gloves, small words, and "for dummies" code as I'm not exactly a heavy hitter.

  • This traffic is over a private line - so my understanding is that ignoring the cert error is not as big a deal as if it were open internet traffic.

  • 并且请 - 孩子手套,小词和“傻瓜”代码,因为我并不是一个重量级的击球手。

  • 此流量通过专用线路 - 所以我的理解是忽略证书错误并不像开放互联网流量那么大。

采纳答案by MattH

The SSL certificate is for a machine to establish a trust relationship. If you type in one IP address, and end up talking to another, that sounds the same as a DNS hiHyman security fault, the kind of thing SSL is intending to help you avoid - and perhaps something you don't want to put up with from "them".

SSL 证书用于机器建立信任关系。如果您输入一个 IP 地址,并最终与另一个 IP 地址交谈,这听起来与 DNS 劫持安全故障相同,SSL 旨在帮助您避免这种情况 - 并且可能是您不想忍受的事情从他们”。

If you may end up talking to more than machine (ideally they would make it appear as one for you), you will need a certificate for each of the possible machines to initiate trust.

如果您最终可能与多台机器交谈(理想情况下,他们会让您看起来像一台机器),您将需要为每台可能的机器提供证书以启动信任。

To ignore trust (I've only ever had to do this temporarily in development scenarios) the following snippet may work for you, but I strongly recommend you consider the impact of ignoring trust before using it:

要忽略信任(我只需要在开发场景中临时执行此操作),以下代码段可能对您有用,但我强烈建议您在使用之前考虑忽略信任的影响:

public static void InitiateSSLTrust()
{
    try
    {
        //Change SSL checks so that all checks pass
        ServicePointManager.ServerCertificateValidationCallback =
           new RemoteCertificateValidationCallback(
                delegate
                { return true; }
            );
    }
    catch (Exception ex)
    {
        ActivityLog.InsertSyncActivity(ex);
    }
}

回答by thomas

This code is much broader than you might expect. It is process-wide. The process might be the exe, IIS on this machine, or even DLLHost.exe. After calling it, have a finally block that restores things to normal by removing the delegate that always returns true.

这段代码比你想象的要广泛得多。它是全流程的。该进程可能是本机上的 exe、IIS,甚至 DLLHost.exe。调用它后,有一个 finally 块,通过删除总是返回 true 的委托来恢复正常。

回答by Jaxidian

This is somewhat the code we're using (not polished yet - I don't think I have the error-handling setup correctly but it should be close) based on thomas's suggestion (this is .NET 4.0 code, though):

根据 thomas 的建议(尽管这是 .NET 4.0 代码),这在某种程度上是我们正在使用的代码(尚未完善 - 我认为我没有正确设置错误处理,但应该很接近):

var sslFailureCallback = new RemoteCertificateValidationCallback(delegate { return true; });

try
{

    if (ignoreSslErrors)
    {
        ServicePointManager.ServerCertificateValidationCallback += sslFailureCallback;
    }

    response = webClient.UploadData(Options.Address, "POST", Encoding.ASCII.GetBytes(Options.PostData));

}
catch (Exception err)
{
    PageSource = "POST Failed:\r\n\r\n" + err;
    return PageSource;
}
finally
{
    if (ignoreSslErrors)
    {
        ServicePointManager.ServerCertificateValidationCallback -= sslFailureCallback;
    }
}

回答by Adam Plocher

I realize this is an old post, but I just wanted to show that there is a more short-hand way of doing this (with .NET 3.5+ and later).

我意识到这是一篇旧帖子,但我只是想表明有一种更快捷的方式来做到这一点(使用 .NET 3.5+ 及更高版本)。

Maybe it's just my OCD, but I wanted to minimize this code as much as possible. This seems to be the shortest way to do it, but I've also listed some longer equivalents below:

也许这只是我的强迫症,但我想尽可能地减少这段代码。这似乎是最短的方法,但我还在下面列出了一些更长的等价物:

// 79 Characters (72 without spaces)
ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => true;

Shortest way in .NET 2.0 (which is what the question was specifically asking about)

.NET 2.0 中的最短路径(这是问题具体询问的内容)

// 84 Characters
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

It's unfortunate that the lambda way requires you to define the parameters, otherwise it could be even shorter.

不幸的是,lambda 方式需要您定义参数,否则它可能会更短。

And in case you need a much longer way, here are some additional alternatives:

如果您需要更长的时间,这里有一些额外的选择:

ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, errors) => true;

ServicePointManager.ServerCertificateValidationCallback = delegate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors) { return true; };

// 255 characters - lots of code!
ServicePointManager.ServerCertificateValidationCallback =
    new RemoteCertificateValidationCallback(
        delegate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            return true;
        });

回答by Jürgen Steinblock

I wanted to disable SSL verification for a specific domain without globally deactivating it because there might be other requests running which should not be affected, so I came up with this solution (please note that uri is a variable inside a class:

我想禁用特定域的 SSL 验证而不全局停用它,因为可能有其他不应该受到影响的请求正在运行,所以我想出了这个解决方案(请注意 uri 是一个类中的变量:

        private byte[] UploadValues(string method, NameValueCollection data)
        {
            var client = new WebClient();

            try
            {
                ServicePointManager.ServerCertificateValidationCallback +=
                    ServerCertificateValidation;

                returnrclient.UploadValues(uri, method, parameters);

            }
            finally
            {
                ServicePointManager.ServerCertificateValidationCallback -=
                    ServerCertificateValidation;
            }
        }

        private bool ServerCertificateValidation(object sender,
            X509Certificate certificate, X509Chain chain,
            SslPolicyErrors sslPolicyErrors)
        {
            var request = sender as HttpWebRequest;
            if (request != null && request.Address.Host.Equals(
                this.uri.Host, StringComparison.OrdinalIgnoreCase))
                return true;
            return false;
        }

回答by MichaelDarkBlue

Here is the VB.net code to make WebClient ignore the SSL cert.

这是使 WebClient 忽略 SSL 证书的 VB.net 代码。

Net.ServicePointManager.ServerCertificateValidationCallback = New Net.Security.RemoteCertificateValidationCallback(Function() True)