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

我有一个简单的web服务调用,由。net (c#) 2.0 Windows应用程序生成,通过Visual Studio生成的web服务代理,用于同样用c#(2.0)编写的web服务。这种方法已经有效了好几年,并且在十几个正在运行的地方继续有效。

在新地点的新安装遇到了问题。当试图调用web服务时,它失败了,消息说:

无法为SSL/TLS安全建立信任关系 频道< / p >

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

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

946762 次浏览

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

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

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

更新链接已修复现在。

如果你使用的是Windows 2003,你可以这样做:

打开微软管理控制台 (Start——> Run——> mmc.exe)

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

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

选择Certificates管理单元,和 单击Add, < / p >

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

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

导航到证书(本地 电脑),并选择一个商店 进口:< / p >

如果您已经拥有根CA证书 对于发行 证书,选择“受信任的根” 认证机构;< / p >

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

右键单击存储,选择“全部” 任务——>导入

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

. 在此之后,简单地重新启动IIS并尝试

.使用实例

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

下面的代码片段将修复您正在调用的服务器上的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;
}

Luke写了一篇关于这个的很好的文章。 非常直截了当。试一下

卢克的解决方案 .

原因(引用自他的文章(减去诅咒)) “. . 上面的代码的问题是,如果您的证书无效,它将无法工作。为什么我要发布到一个网页与无效的SSL证书?因为我很便宜,我不想付钱给Verisign或其他* * -*对我的测试箱进行认证,所以我自己签名。当我发送请求时,我得到一个可爱的异常扔给我:

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

我不知道你,但对我来说,这个异常看起来像是由我的代码中一个愚蠢的错误引起的,导致POST失败。所以我一直在寻找,调整,做各种奇怪的事情。只有在我谷歌了***n的东西,我发现遇到无效的SSL证书后的默认行为是抛出这个异常。 .." < / p >

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

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

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

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

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

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

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

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

“一网打尽”的简单解决方案是:

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

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

我有这个错误运行在一个web服务器的url如下:

a.b.domain.com

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

a_b.domain.com

在这里提示一下这个解因为它在谷歌中出现在最上面。

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

这是我最后做的让它工作:

  • 在我的网站的“绑定…”在IIS中,我必须添加“https”绑定到端口443,并选择“IIS Express development Certificate”。

  • 在我的网站的“高级设置…”我必须将“启用的协议”从“http”更改为“https”。

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

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

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

我的web.config文件已经正确配置,所以在我把上面所有的东西都整理好之后,我就可以继续测试了。

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

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。当你的应用启动时启用托管主机。

我在ie浏览器中的.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

谢谢

如果不是工作坏证书,当ServerCertificateValidationCallback返回true; My ServerCertificateValidationCallback code:

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

对于那些通过VS客户端遇到这个问题的人,一旦成功添加了一个服务引用,并试图执行第一个调用,就会得到这个异常: "底层连接已关闭:无法为SSL/TLS安全通道建立信任关系" 如果您正在使用(像我的例子一样)带有IP地址的端点URL并得到这个异常,那么您可能需要重新添加服务引用,执行以下步骤
  • 在Internet Explorer上打开端点URL。
  • 点击证书错误(地址栏中的红色图标)
  • 单击查看证书。
  • 获取颁发给:“name”并替换IP地址或任何我们正在使用的名称,并得到这个“name”的错误。

重试:)。 由于< / p >

试试这个:

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

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

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

添加:

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

就在你呼叫服务之前

我已经用了一段时间了如果有用的话。

调用方必须显式地请求需要不受信任的认证,并在完成时将回调放回默认状态。

    /// <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;
}
}