无法为SSL / TLS安全通道建立信任关系 - SOAP

时间:2009-03-31 22:07:29

标签: c# .net ssl trust

我有一个简单的Web服务调用,由.NET(C#)2.0 Windows应用程序通过Visual Studio生成的Web服务代理生成,用于也使用C#(2.0)编写的Web服务。这已经工作了好几年了,并且在它运行的十几个地方继续这样做。

新网站上的新安装遇到问题。尝试调用Web服务时,它失败并显示消息:

  

无法为SSL / TLS安全建立信任关系   信道

Web服务的URL使用SSL(https://) - 但这已经在许多其他位置工作了很长时间(并且仍在继续)。

我在哪里看?这可能是Windows和.NET之间的安全问题吗?如果是这样,我在哪里建立信任关系?我迷路了!

18 个答案:

答案 0 :(得分:346)

以下代码段将修复您正在呼叫的服务器上的SSL证书有问题的情况。例如,它可能是自签名的,或者证书与服务器之间的主机名可能不匹配。

这是危险的,如果您正在直接控制之外调用服务器,因为您无法确定是否正在与您认为已连接的服务器通话。但是,如果您正在处理内部服务器并且获得“正确”证书是不切实际的,请使用以下命令告知Web服务忽略证书问题并勇敢地参与其中。

前两个使用lambda表达式,第三个使用常规代码。第一个接受任何证书。最后两个至少检查证书中的主机名是否是您期望的主机名 ...希望你觉得有用

//Trust all certificates
System.Net.ServicePointManager.ServerCertificateValidationCallback =
    ((sender, certificate, chain, sslPolicyErrors) => true);

// trust sender
System.Net.ServicePointManager.ServerCertificateValidationCallback
                = ((sender, cert, chain, errors) => cert.Subject.Contains("YourServerName"));

// validate cert by calling a function
ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(ValidateRemoteCertificate);

// callback used to validate the certificate in an SSL conversation
private static bool ValidateRemoteCertificate(object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors policyErrors)
{
    bool result = cert.Subject.Contains("YourServerName");
    return result;
}

答案 1 :(得分:160)

非常简单的“全能”解决方案就是:

System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

塞巴斯蒂安 - 卡斯塔尔迪的解决方案更为详细。

答案 2 :(得分:157)

思考(基于过去的痛苦):

  • 你有服务器的DNS和视线吗?
  • 您使用的是证书中的正确名称吗?
  • 证书仍然有效吗?
  • 是一个配置不当的负载均衡器吗?
  • 新的服务器机器是否正确设置了时钟(即使UTC时间正确[忽略当地时间,这在很大程度上是无关紧要的]) - 这对WCF来说无疑是重要的,因此可能会影响常规SOAP?
  • 是否存在证书信任链问题?如果您从服务器浏览到soap服务,是否可以获得SSL?
  • 与上述相关 - 证书是否已安装到正确的位置? (您可能需要受信任的根证书颁发机构中的副本)
  • 是服务器的机器级代理设置正确吗? (与用户的代理不同);请参阅XP / 2003的proxycfg(不确定Vista等)

答案 3 :(得分:32)

我个人最喜欢以下解决方案:

using System.Security.Cryptography.X509Certificates;
using System.Net.Security;

...然后在您请求获取错误之前,请执行以下操作

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

在咨询Luke's Solution

后找到了这个

答案 4 :(得分:18)

如果您使用的是Windows 2003,可以试试这个:

  

打开Microsoft管理控制台   (开始 - >运行 - > mmc.exe);

     

选择文件 - >添加/删除管理单元;

     

在Standalone选项卡中,选择Add;

     

选择“证书”管理单元,然后选择   单击添加;

     

在向导中,选择“计算机”   帐户,然后选择本地   电脑。按完成结束   向导;

     

关闭“添加/删除管理单元”对话框;

     

导航到证书(本地   电脑)并选择一家商店   输入:

     

如果您拥有根CA证书   对于发行的公司   证书,选择“受信任的根”   认证机构;

     

如果你有证书   服务器本身,选择其他人

     

右键单击商店,然后选择全部   任务 - >导入

     

按照向导提供   您拥有的证书文件;

     

之后,只需重新启动IIS并尝试   再次调用Web服务。

参考:http://www.outsystems.com/NetworkForums/ViewTopic.aspx?Topic=Web-Services:-Could-not-establish-trust-relationship-for-the-SSL/TLS- ...

答案 5 :(得分:15)

如果您不想盲目地信任每个人并仅为某些主机设置信任例外,则以下解决方案更合适。

public static class Ssl
{
    private static readonly string[] TrustedHosts = new[] {
      "host1.domain.com", 
      "host2.domain.com"
    };

    public static void EnableTrustedHosts()
    {
      ServicePointManager.ServerCertificateValidationCallback = 
      (sender, certificate, chain, errors) =>
      {
        if (errors == SslPolicyErrors.None)
        {
          return true;
        }

        var request = sender as HttpWebRequest;
        if (request != null)
        {
          return TrustedHosts.Contains(request.RequestUri.Host);
        }

        return false;
      };
    }
}

然后在你的应用程序启动时调用Ssl.EnableTrustedHosts。

答案 6 :(得分:7)

Microsoft的SSL Diagnostics Tool可能有助于确定问题。

更新此链接现已修复。

答案 7 :(得分:6)

卢克写了一篇关于这篇文章的相当不错的文章。 非常直接..试一试

Luke's Solution

原因(引自他的文章(减去诅咒)) ” ..  上面代码的问题是,如果您的证书无效,它将不起作用。为什么我要发布到具有无效SSL证书的网页?因为我便宜而且我不想支付Verisign或其他 ** - * s来获得我的测试盒的证书所以我自己签了它。当我发出请求时,我得到了一个可爱的例外:

<强> System.Net.WebException 底层连接已关闭。无法与远程服务器建立信任关系。

我不了解你,但对我而言,异常看起来像是由于我的代码中的一个愚蠢的错误导致POST失败而引起的。所以我一直在搜索,调整和做各种奇怪的事情。只有在我搜索了***之后,才发现遇到无效SSL证书后的默认行为是抛出这个异常。 ..“

答案 8 :(得分:3)

我刚遇到这个问题。我的决心是通过手动同步到时间服务器来更新系统时间。要做到这一点,你可以:

  • 右键单击任务栏中的时钟
  • 选择Adjust Date/Time
  • 选择Internet Time标签
  • 点击Change Settings
  • 选择Update Now

在我的情况下,这是同步错误所以我必须多次点击它才能正确更新。如果它继续不正确地更新,您甚至可以尝试使用服务器下拉列表中的其他时间服务器。

答案 9 :(得分:3)

我在Internet Explorer的.NET应用中遇到了类似的问题。

我解决了将证书(在我的案例中为VeriSign Class 3证书)添加到可信编辑证书的问题。

Go to Internet Options-> Content -> Publishers and import it

如果您从以下位置导出证书,则可以获取证书:

Internet Options-> Content -> Certificates -> Intermediate Certification Authorities -> VeriSign Class 3 Public Primary Certification Authority - G5

感谢

答案 10 :(得分:2)

试试这个:

System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Tls12;

请注意,您必须至少使用4.5 .NET framework

答案 11 :(得分:1)

我在使用url的网络服务器上运行此错误:

a.b.domain.com

但没有证书,所以我得到了一个名为

的DNS
a_b.domain.com

这里只是提示这个解决方案,因为这在google中名列前茅。

答案 12 :(得分:1)

添加此内容:

 ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;}

在您致电该服务的行之前

答案 13 :(得分:1)

对于那些通过VS客户端遇到此问题的人,一旦成功添加服务引用并尝试执行第一次调用就会遇到此异常: “底层连接已关闭:无法为SSL / TLS安全通道建立信任关系” 如果您正在使用(就像我的情况一样)具有IP地址的端点URL并获得此异常,那么您可能需要重新添加服务引用,执行以下步骤:

  • 在Internet Explorer上打开端点URL。
  • 点击证书错误(地址栏中的红色图标)
  • 点击查看证书。
  • 抓住发给:&#34;名称&#34;并替换我们正在使用的IP地址或任何名称并获取此错误&#34; name&#34;。

再试一次:)。 感谢

答案 14 :(得分:0)

我使用了一段时间的变体,如果有帮助的话。

调用方必须明确请求需要不受信任的证书,并在完成后将回调放回默认状态。

    /// <summary>
    /// Helper method for returning the content of an external webpage
    /// </summary>
    /// <param name="url">URL to get</param>
    /// <param name="allowUntrustedCertificates">Flags whether to trust untrusted or self-signed certificates</param>
    /// <returns>HTML of the webpage</returns>
    public static string HttpGet(string url, bool allowUntrustedCertificates = false) {
        var oldCallback = ServicePointManager.ServerCertificateValidationCallback;
        string webPage = "";
        try {
            WebRequest req = WebRequest.Create(url);

            if (allowUntrustedCertificates) {
                // so we can query self-signed certificates
                ServicePointManager.ServerCertificateValidationCallback = 
                    ((sender, certification, chain, sslPolicyErrors) => true);
            }

            WebResponse resp = req.GetResponse();
        
            using (StreamReader sr = new StreamReader(resp.GetResponseStream())) {
                webPage = sr.ReadToEnd().Trim();
                sr.Close();
            }
            return webPage;
        }
        catch {
            // if the remote site fails to response (or we have no connection)
            return null;
        }
        finally {
            ServicePointManager.ServerCertificateValidationCallback = oldCallback;
        }
    }

答案 15 :(得分:0)

我的解决方案(VB.Net,此应用程序的“ staging”(UAT)版本需要使用“ staging”证书,但在请求进入实时站点后不影响请求):

table_src = html.text.split('<div class="overthrow table_container" 
id="div_team-stats-per_game">')[1].split('</table>')[0] + '</table>'

table = BeautifulSoup(table_src, 'lxml')

答案 16 :(得分:0)

就我而言,我尝试使用IIS 7在Visual Studio环境中测试 SSL

这是我最终要做的工作:

  • 在IIS右侧“绑定...”部分的网站中,我必须将“https”绑定添加到端口443并选择“IIS Express开发证书”。

    < / LI>
  • 在我右侧“高级设置...”部分的网站中,我必须将“启用的协议”从“http”更改为“https”。

  • 在“SSL设置”图标下,我为客户端证书选择了“接受”。

  • 然后我不得不回收应用池。

  • 我还必须使用mmc.exe将本地主机证书导入我的个人商店。

我的web.config文件已经配置正确,所以在我完成上述所有操作后,我就可以继续测试了。

答案 17 :(得分:-4)

如果不是工作错误的sertificate,当ServerCertificateValidationCallback返回true; 我的ServerCertificateValidationCallback代码:

ServicePointManager.ServerCertificateValidationCallback += delegate
{
    LogWriter.LogInfo("Проверка сертификата отключена, на уровне ServerCertificateValidationCallback");
    return true;
};

阻止执行ServerCertificateValidationCallback:

的代码
     if (!(ServicePointManager.CertificatePolicy is CertificateValidation))
    {
        CertificateValidation certValidate = new CertificateValidation();
        certValidate.ValidatingError += new CertificateValidation.ValidateCertificateEventHandler(this.OnValidateCertificateError);
        ServicePointManager.CertificatePolicy = certValidate;
    }

OnValidateCertificateError函数:

private void OnValidateCertificateError(object sender, CertificateValidationEventArgs e)
{
    string msg = string.Format(Strings.OnValidateCertificateError, e.Request.RequestUri, e.Certificate.GetName(), e.Problem, new Win32Exception(e.Problem).Message);
    LogWriter.LogError(msg);
    //Message.ShowError(msg);
}

我禁用了CertificateValidation代码并且ServerCertificateValidationCallback运行得非常好