我有一个简单的Web服务调用,由.NET(C#)2.0 Windows应用程序通过Visual Studio生成的Web服务代理生成,用于也用C#(2.0)编写的Web服务.这已经工作了几年,并且在它运行的十几个地方继续这样做.
新站点的新安装遇到问题.尝试调用Web服务时,它失败并显示以下消息:
无法为SSL/TLS安全通道建立信任关系
Web服务的URL使用SSL(https://) - 但这已经在很多其他位置工作了很长时间(并且仍在继续).
我在哪里看?这可能是Windows和.NET之间的安全问题吗?如果是这样,我在哪里建立信任关系?我迷路了!
以下代码段将修复您正在调用的服务器上的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; }
非常简单的"全能"解决方案是这样的:
System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
sebastian-castaldi的解决方案更为详细.
思考(基于过去的痛苦):
你有服务器的DNS和视线吗?
你使用证书中的正确名称?
证书仍然有效吗?
是一个配置不当的负载均衡器弄乱了吗?
新的服务器机器是否正确设置了时钟(即使UTC时间正确[忽略本地时间,这在很大程度上是无关紧要的]) - 这对WCF来说无疑是重要的,因此可能影响常规SOAP?
有证书信托链问题吗?如果你从服务器浏览到soap服务,你能获得SSL吗?
与上述相关 - 证书是否已安装到正确的位置?(您可能需要受信任的根证书颁发机构中的副本)
服务器的机器级代理设置是否正确?(与用户的代理不同); 看看XP/2003的proxycfg(不确定Vista等)
我个人最喜欢以下解决方案:
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的解决方案之后找到了这个
如果您使用的是Windows 2003,则可以尝试以下操作:
打开Microsoft管理控制台(开始 - >运行 - > mmc.exe);
选择"文件" - >"添加/删除管理单元";
在"独立"选项卡中,选择"添加";
选择"证书"管理单元,然后单击"添加";
在向导中,选择"计算机帐户",然后选择"本地计算机".按"完成"结束向导;
关闭"添加/删除管理单元"对话框;
导航到证书(本地计算机)并选择要导入的商店:
如果您拥有颁发证书的公司的根CA证书,请选择"受信任的根证书颁发机构";
如果您拥有服务器本身的证书,请选择"其他人"
右键单击该存储,然后选择"所有任务" - >"导入"
按照向导提供您拥有的证书文件;
之后,只需重新启动IIS并尝试再次调用Web服务.
参考:http://www.outsystems.com/NetworkForums/ViewTopic.aspx?Topic = Web- Services : -Could-not-establish-trust-relationship-for- the- SSL/ TLS- ...
如果您不想盲目地信任每个人并仅对某些主机进行信任例外,则以下解决方案更合适.
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.
Microsoft的SSL诊断工具可能有助于识别问题.
更新链接现已修复.
卢克写了一篇关于这篇文章的相当不错的文章..非常直截了当..试一试
卢克的解决方案
原因(引用他的文章(减去诅咒))"..上面代码的问题是,如果你的证书无效,它就不起作用.为什么我要发布到一个有无效SSL证书的网页呢?因为我很便宜而且我不想支付Verisign或者其他** -*s用于我的测试盒的证书,所以我自己签了.当我发出请求时,我得到了一个可爱的例外:
System.Net.WebException 底层连接已关闭.无法与远程服务器建立信任关系.
我不了解你,但对我来说,异常看起来像我的代码中导致POST失败的愚蠢错误.所以我一直在搜索,调整和做各种奇怪的事情.只有在我搜索了***之后,才发现遇到无效SSL证书后的默认行为是抛出这个异常..."