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

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


无法建立SSL / TLS安全通道的信任关系。 />
Web服务的URL使用SSL(https://)-但是它已经在许多其他地方使用了很长时间(并且将继续这样做)。

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

评论

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

#1 楼

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


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


评论


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

–Rob Schripsema
09年3月31日在22:21

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

– Marc Gravell♦
09年3月31日在22:27

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

–p。坎贝尔
09年12月3日在16:54

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

–Chris-Haddox Technologies
13年2月22日在16:05

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

–罗斯金
2014年10月9日10:53

#2 楼

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


评论


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

– Amzath
2012年11月14日19:31

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

– RJB
2015年9月14日在2:54

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

–艾萨克·莱曼(Isaac Lyman)
16年5月5日在16:12

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

–迈克·张伯伦
16 Mar 22 '16 at 0:19

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

–艾萨克·莱曼(Isaac Lyman)
16-3-22在17:01

#3 楼

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

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


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

评论


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

–cjbarth
13年8月19日在15:41

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

–allen1
15-10-27在17:41

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

–李吉申
16年4月9日在9:48

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

–神龙
17年6月27日在9:42

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

–雷米
18年3月22日在18:37

#4 楼

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

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解决方案后发现了这个

评论


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

–爱德华·布雷(Edward Brey)
2014年2月11日下午16:05

在生产中使用此功能有什么安全隐患?

–阿姆贾德
18年3月22日在12:25

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

–1800信息
18年7月1日在23:28

VB.NET:System.Net.ServicePointManager.ServerCertificateValidationCallback =函数(作为对象,作为X509证书的证书,作为X509链的证书,作为SslPolicyErrors的SslPolicyErrors)True

–gotorg
20 Nov 12'23:48

#5 楼

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

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
18年1月24日在5:05

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

–阿姆贾德
18年3月22日在12:25

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

–Rob Prouse
18年3月29日在15:29

当IAM使用WCF插件从wsdl生成类时,它应该工作吗?

–卡米尔
19年8月7日在10:14

#6 楼

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


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

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

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

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

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

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

导航到“证书(本地
计算机)”并选择要导入
的商店:

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

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

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

遵循向导并提供您拥有的
证书文件;

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

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

评论


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

–雅各布·埃瓦尔德(Jacob Ewald)
14年4月17日在17:14

#7 楼

卢克(Luke)对此写了一篇很好的文章..
很简单..试试看

卢克(Luke)的解决方案

原因(引述他的文章(减去诅咒))
“ ..
上面的代码的问题是,如果您的证书无效,它就不起作用。为什么我要使用无效的SSL证书发布到网页上? “价格便宜,我不想在测试箱中支付Verisign或其他**-*作为证书的费用,所以我对它进行了自签名。当我发送请求时,我遇到了一个可爱的异常: br />
System.Net.WebException
基础连接已关闭。无法与远程服务器建立信任关系。

我不认识你,但对我来说那个异常看起来像是由于我的代码中的一个愚蠢的错误导致POST失败而导致的,所以我一直在搜索,并进行调整和做各种奇怪的事情。发现默认行为在遇到无效的SSL证书后,我将抛出此异常。
..“

评论


.Net 4.5不建议使用此解决方案。如果您只想接受所有证书,请在下面进一步查看Sebastian Castaldi或我的回答。

–雷米
13年3月18日在17:57

#8 楼

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

UPDATE链接已得到修复。

评论


截至今天(2012年8月),该链接已断开。

–ashes999
2012年8月10日16:18

搜索了下载目录,并且不再有SSL诊断工具可用。 :(

– SASS_Shooter
2012年9月6日在21:46

让我们修复链接。纠正我,如果我错了iis.net/downloads/community/2009/09/…

– Amzath
2012年11月14日19:32



#9 楼

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


右键单击任务栏中的时钟
选择Adjust Date/Time

选择Internet Time选项卡
单击Change Settings

选择Update Now


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

评论


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

–TheGerm
2014年1月27日在17:55

#10 楼

尝试以下操作:

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


请注意,至少必须使用4.5 .NET Framework。

#11 楼

我在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


感谢

#12 楼

添加以下内容:
 ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;}

正好在您拨打服务电话的那一行之前

评论


这对我有用,谢谢!我试图从.NET客户端应用程序发布和获取到localhost API,即使我可以使用YARC插件通过浏览器访问该API(但另一个REST Client),也无法使其正常工作。这行代码使我的.NET应用程序可以访问API。

– Smitty-Werben-Jager-Manjenson
20年6月30日在15:53

#13 楼

我在具有以下网址的Web服务器上运行此错误:

a.b.domain.com


,但是没有证书,因此我得到了一个名为

a_b.domain.com


,因为在Google上排名最高,所以只需在此处提示此解决方案即可。

评论


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

–sree
16年1月31日在23:09



#14 楼

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


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

再试一次:)。
谢谢

#15 楼

在我的情况下,我试图使用IIS 7在Visual Studio环境中测试SSL。

为了使它正常工作,我最终要做的是:


在我网站的IIS右侧“绑定...”部分下,我必须将“ https”绑定添加到端口443,然后选择“ IIS Express开发证书”。
在我网站下的“我必须将“已启用的协议”从“ http”更改为“ https”。
在“ SSL设置”图标下,我为客户端证书选择了“接受”。
然后我必须回收应用程序池。
我还必须使用mmc.exe将本地主机证书导入到我的个人存储中。

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

评论


您的web.config如何配置?

– Chazt3n
16 Mar 4 '16 at 3:44

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

– Popo
16 Mar 4 '16 at 17:15

#16 楼

我的解决方案(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


#17 楼

我使用了一段时间的变体可以帮助任何人。
调用方必须明确请求要求不受信任的证书,并在完成后将回调放回默认状态。
    /// <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;
        }
    }


#18 楼

如果无效的证书无效,则当ServerCertificateValidationCallback返回true时;
我的ServerCertificateValidationCallback代码:

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

/>
     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运行得很好

评论


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

–丹
18年1月8日在10:12

在生产中使用此功能有什么安全隐患?

–阿姆贾德
18 Mar 22 '18 at 12:26