364

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

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

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

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

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

4

19 回答 19

392

以下代码段将修复您调用的服务器上的 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;
}
于 2011-07-07T15:52:52.180 回答
200

非常简单的“包罗万象”解决方案是这样的:

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

sebastian-castaldi 的解决方案更详细一些。

于 2013-03-18T18:00:00.827 回答
185

想法(基于过去的痛苦):

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

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

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

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

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

在咨询卢克的解决方案后发现了这个

于 2013-02-26T22:59:24.083 回答
23

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

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。

于 2014-10-08T07:58:09.103 回答
18

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

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

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

在独立选项卡中,选择添加;

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

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

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

导航到证书(本地计算机)并选择要导入的存储:

如果您拥有颁发证书的公司的 Root CA 证书,请选择 Trusted Root Certification Authorities;

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

右键单击商店并选择所有任务 --> 导入

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

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

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

于 2011-03-25T00:10:56.250 回答
7

Microsoft 的SSL 诊断工具可能能够帮助识别问题。

更新链接现已修复。

于 2009-03-31T22:36:53.010 回答
7

卢克写了一篇关于这个的很好的文章..非常直接..试试这个

卢克的解决方案

原因(引用他的文章(减去诅咒))“.. 上面代码的问题是,如果您的证书无效,它就不起作用。为什么我要发布到带有无效 SSL 证书的网页?因为我很便宜,我不想向 Verisign 或其他**- *s 支付我的测试箱的证书,所以我自己签署了它。当我发送请求时,我收到了一个可爱的异常:

System.Net.WebException 基础连接已关闭。无法与远程服务器建立信任关系。

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

于 2012-10-25T19:36:27.027 回答
3

我刚遇到这个问题。我的解决方案是通过手动同步到时间服务器来更新系统时间。为此,您可以:

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

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

于 2013-02-22T16:09:16.513 回答
3

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

我解决了将证书(在我的情况下为 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

谢谢

于 2015-05-25T14:07:40.047 回答
3

试试这个:

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

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

于 2018-05-15T12:23:57.917 回答
2

添加这个:

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

就在您调用服务的那一行之前

于 2020-06-23T12:17:17.590 回答
1

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

a.b.domain.com

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

a_b.domain.com

只是在此处提示此解决方案,因为这在谷歌中名列前茅。

于 2014-01-22T13:28:26.940 回答
1

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

  • 在 Internet Explorer 上打开端点 URL。
  • 单击证书错误(地址栏中的红色图标)
  • 单击查看证书。
  • 获取发布到:“名称”并替换 IP 地址或我们使用的任何名称,并获取此“名称”的错误。

再试一次 :)。谢谢

于 2017-06-12T20:28:05.013 回答
0

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

这就是我最终为了让它工作而做的事情:

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

  • 在右侧“高级设置...”部分的我的站点下,我必须将“启用的协议”从“http”更改为“https”。

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

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

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

我的web.config文件已经正确配置,所以在我整理完以上所有内容后,我就可以继续我的测试了。

于 2014-02-17T17:55:24.130 回答
0

我的解决方案(VB.Net,此应用程序的“暂存”(UAT)版本需要使用“暂存”证书,但一旦它们在实时站点上就不会影响请求):

    ...
        Dim url As String = ConfigurationManager.AppSettings("APIURL") & "token"
        If url.ToLower().Contains("staging") Then
           System.Net.ServicePointManager.ServerCertificateValidationCallback = AddressOf AcceptAllCertifications
        End If
    ...

    Private  Function AcceptAllCertifications(ByVal sender As Object, ByVal certification As System.Security.Cryptography.X509Certificates.X509Certificate, ByVal chain As System.Security.Cryptography.X509Certificates.X509Chain, ByVal sslPolicyErrors As System.Net.Security.SslPolicyErrors) As Boolean
        Return True
    End Function
于 2019-07-15T02:05:24.867 回答
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;
        }
    }
于 2020-10-20T07:25:48.033 回答
0

实际上,此问题来自 SSL/TLS 证书问题,因此您可以使用以下代码找到问题:

这是最好的解决方案 https://indiabix.info/id/16/the-underlying-conne

于 2022-02-19T10:41:54.713 回答
-2

如果不工作坏证书,当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 运行得很好

于 2017-01-10T11:17:07.717 回答