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


325

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

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

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

Web服务的URL使用SSL(https://)-但这已经在许多其他地方使用了很长时间了(并将继续这样做)。

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


就我而言,此错误是由IP地址转发引起的。
cja

Answers:


166

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

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

2
1)Web服务在Web上。我们可以通过浏览器浏览到它。2)新机器不是服务器-它是运行我的应用程序的桌面,该应用程序收集订单信息并通过SOAP服务上传。3)是,我们可以浏览到它。4)这对我来说是新的:机器级代理?
罗布·施里普塞玛

2
是; 代码不使用IE代理设置;它使用单独的存储库。配置此文件(如果使用代理服务器)很重要。在XP上,最简单的选项是(IIRC)“ proxycfg -i”来导入IE设置。
Marc Gravell

11
谢谢马克。这对我有帮助,问题是服务器上有一个我尚未信任的第三方CA签署的证书。解决方案是将该CA添加到“受信任的根CA”列表中。
p.campbell

1
出现此异常的计算机无法使用时间服务器同步系统时间。在工作之前,我必须手动输入时间。
克里斯-Haddox Technologies

4
如果您一直在使用Fiddler调试服务调用并已使用其证书拦截模式,则可能会得到此信息。只需删除提琴手的选项中的拦截即可,您应该会很好
Ruskin 2014年

363

以下代码片段将解决您正在呼叫的服务器上的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;
}

6
我在ServicePointManager方面的经验。对其进行任何更改都会影响整个应用程序域。尽管答案很清楚地说明了如何应用,但我还是想提出这一点。
Amzath 2012年

对我来说,设置回调适用于.NET 4.5,但不适用于.NET 4.6
RJB

@Amzath有关在完成特定请求后如何重置此设置的任何建议?一个人可能需要向未经认证的服务器发出一个请求,然后将其恢复原状。
艾萨克·莱曼

1
@Isaac Lyman:ServicePointManager.ServerCertificateValidationCallback = null;应该恢复为默认行为。
Mike Chamberlain

1
@MikeChamberlain您的建议的唯一问题是,由于您正在处理全局应用程序设置,因此并发请求可能会变得不安全。
艾萨克·莱曼

178

非常简单的“全部捕获”解决方案是这样的:

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

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


21
我只是将其放在一条#If CONFIG = "Debug"语句中,以便仅在调试模式下才将其激活。效果很好!
cjbarth

1
细节可能很好,但是对于快速,简短和轻松的代码行,也有话要说。这段代码很短,可以解决问题。
allen1 2015年

这只会对当前的动作起作用(例如使用ASP MVC)吗?还是将其设置为ASP.NET应用程序的默认行为?
JeeShen Lee

2
这仅应用于测试目的,此解决方案信任任何证书,甚至无效/过期的证书
Shenron

1
如以上注释中所述,这不再验证SSL连接是否有效。因此,您的系统与其他系统之间的连接可能会受到损害。这始终是您需要什么的问题。
雷米

35

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

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

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

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

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


4
有关此方法的安全性警告,请参见Sebastian Castaldi的答案。
Edward Brey 2014年

在生产中使用此功能的安全风险是什么?
Amjad

@Amjad的安全风险是它完全避开了使用SSL / TLS的任何好处。服务器可以提供自己喜欢的任何证书,并且此代码将忽略该错误
1800信息

18

如果您使用的是Windows 2003,则可以尝试以下操作:

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

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

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

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

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

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

导航到证书(本地计算机),然后选择要导入的商店:

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

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

右键单击商店,然后选择“所有任务->导入”

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

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

参考:http : //www.outsystems.com/NetworkForums/ViewTopic.aspx ? Topic = Web服务:- 无法建立信任关系 -用于SSL / TLS- ...


2
这让我成为了其中的一部分,但是我需要在“受信任的根证书颁发机构”部分中拥有该证书,才能使其正常工作。根据blogs.msdn.com/b/jpsanders/archive/2009/09/16/…–
Jacob Ewald

17

如果您不想盲目地信任所有人,并且只对某些主机设置信任例外,则以下解决方案更合适。

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。


@thelem是的重新阅读我想我一定是第一次读错了
Shiv

信任生产中所有证书的安全风险是什么?
Amjad

@Amjad的安全风险在于,客户端和服务器之间的任何人都可以将自己插入通信中间,使用自己的SSL证书并读取客户端和服务器之间的所有流量。这样做实际上会使SSL失效。
罗伯·普劳斯

IAM使用WCF插件从wsdl生成类时是否应该工作?
卡米尔

7

卢克(Lake)对此写了一篇很好的文章。

卢克的解决方案

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

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

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


1
.Net 4.5不建议使用此解决方案。如果您只想接受所有证书,请参阅下面的塞巴斯蒂安·卡斯塔尔迪(Sebastian Castaldi)或我的答案。
雷米


3

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

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

就我而言,这是不正确地同步的,因此我必须单击几次才能正确更新。如果继续错误更新,您甚至可以尝试使用服务器下拉列表中的其他时间服务器。


天啊。猛击这确切的东西。感谢您轻松修复!
TheGerm 2014年


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

谢谢


1

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

a.b.domain.com

但是没有证书,所以我有了一个DNS

a_b.domain.com

自从在Google上排名第一以来,这里只是向该解决方案提供了提示。


就我而言,网站是根据通配符ssl证书(* .abcd.com)配置的。配置后,网站绑定就像xyz-abcd.com一样导致了问题。
2016年

1

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

  • 在Internet Explorer上打开端点URL。
  • 单击证书错误(地址栏中的红色图标)
  • 单击查看证书。
  • 将发出的内容抓到“名称”,然后替换IP地址或我们使用的任何名称,并得到该“名称”的错误。

再试一次 :)。谢谢


0

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

我最终要做的就是使它工作:

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

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

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

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

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

我的web.config文件已经正确配置,因此,在整理完上述所有内容之后,我便可以继续进行测试。


您的web.config如何配置?
Chazt3n

@ Chazt3n我不能告诉你,那是一段时间了,但是那将是一个基本的http绑定设置,我通常使用svcutil为Web服务客户端信息生成配置信息。
Popo

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

-3

如果证书无效,则在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运行得很好


您永远不要禁用任何证书验证。相反,请解决导致验证失败的问题。

在生产中使用此功能的安全风险是什么?
Amjad
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.