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

发布于 2024-08-02 18:38:45 字数 2416 浏览 7 评论 0原文

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

下面是代码的精简版本:

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
}

这是我得到的错误:

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

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

据称,该证书是我们服务器上“就在那里”的众多威瑞信证书之一。我见过的忽略证书错误的示例似乎都暗示请求者正在附加特定的 x509 证书(我没有)。

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

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

  • 请-小手套,小词,和“傻瓜”代码,因为我不完全是一个重击手。

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

Using 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.

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.

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).

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.

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

我乃一代侩神 2024-08-09 18:38:46

SSL证书是供机器建立信任关系的。如果您输入一个 IP 地址,最终与另一个 IP 地址通信,这听起来与 DNS 劫持安全故障相同,SSL 旨在帮助您避免这种情况 - 也许您不想忍受这种情况来自“他们”。

如果您最终可能会与多个机器对话(理想情况下它们会使其显示为适合您的机器),则您将需要为每台可能的机器提供证书以启动信任。

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

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);
    }
}

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 hijack 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".

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);
    }
}
财迷小姐 2024-08-09 18:38:46

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

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

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

Shortest way in .NET 2.0(这是问题具体询问的内容)

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

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

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

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;
        });

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).

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)

// 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.

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;
        });
疯狂的代价 2024-08-09 18:38:46

这在某种程度上是我们正在使用的代码(尚未完善 - 我认为我的错误处理设置不正确,但它应该接近),基于 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;
    }
}

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):

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;
    }
}
旧伤慢歌 2024-08-09 18:38:46

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

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.

如果没有 2024-08-09 18:38:46

我想禁用特定域的 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;
        }

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:

        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;
        }
筱武穆 2024-08-09 18:38:46

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

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

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

Net.ServicePointManager.ServerCertificateValidationCallback = New Net.Security.RemoteCertificateValidationCallback(Function() True)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文