如何解决“无法为 SSL/TLS 安全信道建立有权限的信任关系”的问题

我有一个使用 HTTPS 托管在 IIS7中的 WCF 服务。当我用 Internet Explorer 浏览这个网站时,它非常有效,这是因为我在本地的根证书权威商店中添加了这个证书。

我在一台机器上开发,所以客户端和服务器是同一台机器。证书是直接从 IIS7管理单元进行自签名的。

现在我不断地得到这个错误..。

无法为具有权限的 SSL/TLS 安全通道建立信任关系。

... 当从客户端控制台呼叫时。

我手动给自己权限和网络服务的证书,使用 findprivatekey和使用 cacls.exe

我尝试使用 SOAPUI 连接到服务,这是可行的,因此这肯定是我的客户端应用程序中的一个问题,它是基于过去使用 http 的代码。

我还能去哪里找我似乎已经用尽了所有的可能性,为什么我不能连接?

382230 次浏览

作为一种变通方法,你可以在客户端向 ServicePointManagerServerCertificateValidationCallback添加一个处理程序:

System.Net.ServicePointManager.ServerCertificateValidationCallback +=
(se, cert, chain, sslerror) =>
{
return true;
};

但是请注意,这不是一个好的做法完全忽略服务器证书,并告诉服务点管理器,无论什么证书都没有问题,这会严重影响客户机安全性。您可以对此进行细化,并执行一些自定义检查(针对证书名称、散列等)。 在使用测试证书时,至少可以避免开发过程中出现的问题。

出现问题是因为您使用的是自签名密钥。客户端不信任这个密钥,密钥本身也不提供可验证的链或证书吊销列表。

你有几个选择,你可以

  1. 关闭证书验证 客户(错误的举动,男子在 中间的攻击比比皆是

  2. 使用 makecert 创建根 CA 和 从中创建证书(ok 移动,但仍然没有 CRL)

  3. 创建一个内部根 CA Windows 证书服务器或其他 PKI 解决方案然后信任该根 Cert (管理起来有点麻烦)

  4. 购买 SSL 证书 值得信任的 CA (昂贵的)

将此添加到您的客户端代码中:

ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(
delegate
{
return true;
});

我也遇到了同样的问题,我用两种方法解决了它: 首先,我将 MMC 管理单元“证书”用于“计算机帐户”,并将自签名证书拖到“可信根证书颁发机构”文件夹中。这意味着本地计算机(生成证书的计算机)现在将信任该证书。 其次,我注意到证书是为一些内部计算机名生成的,但 Web 服务是使用另一个名称访问的。这在验证证书时造成了不匹配。我们为 Computer.opers.local 生成了证书,但是使用 https://computer.internaldomain.companydomain.com访问了 Web 服务。当我们将 URL 切换到用于生成证书的 URL 时,就不会再出现错误了。

也许只是切换 URL 就可以了,但是通过让证书可信,你也可以避免出现红色 Internet Explorer,告诉你它不信任证书。

我在自签证书方面也有类似的问题。 我可以使用与服务器的 FQDN 相同的证书名来解决这个问题。

理想情况下,应该在服务器端管理 SSL 部分。客户端不需要安装任何 SSL 证书。另外,有些文章提到从客户机代码中绕过 SSL。但我完全不同意。

前两个使用 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 = false;
if (cert.Subject.ToUpper().Contains("YourServerName"))
{
result = true;
}


return result;
}

当我遇到这个问题时,是因为 client.config 的端点如下:

 https://myserver/myservice.svc

但是证书是预期的

 https://myserver.mydomain.com/myservice.svc

更改端点以匹配服务器的 FQDN 解决了我的问题。我知道这不是问题的唯一原因。

我只是将证书拖放到“ Trusted Root 證书颁发机构”文件夹中,瞧,一切工作都很顺利。

哦,我首先从管理员命令提示符中添加了以下内容:

netsh http add urlacl url=https://+:8732/Servicename user=NT-MYNDIGHET\INTERAKTIV

我不确定你需要用户的名字(我的名字是挪威的,你可以看到!) : user=NT-AUTHORITY/INTERACTIVE

您可以通过发出命令 netsh http show urlacl查看所有现有的 urlacl

这是在尝试通过以下方式连接到 WCF 服务时发生的。当使用与名称绑定的证书时,例如: mysite.com。

切换到 https://mysite.com:port/MyService.svc解决了这个问题。

请按照以下步骤:

  1. 在 IE 中打开服务链接。

  2. 单击地址栏中的证书错误提示,然后单击查看证书。

  3. 发给: 姓名的支票。

  4. 获取发出的名称,并将服务和客户端端点基地址名称中的 localhost 提及替换为完全限定域名(FQDN)。

例如: https://abc0:203/sampleservice.svc 敬 https://abc0:203/sampleservice.svc

我也有同样的问题。我还在本地商店中添加了 CA 证书,但是方法不对。

使用 mmc Console (Start-> Run-> Mmc) ,您应该添加 证书管理单元作为 Service 帐户(选择 IIS 的服务帐户)或 Computer 帐户(它为机器上的每个帐户添加)

这是我所说的图像 Add snap-in for a service account or the computer account

从现在开始,您可以添加 CA 证书(受信任的根 CA中级核证机关) ,一切都将正常工作

当使用绑定到某个名称(如 host.mysite.com)的证书时,只使用主机名(如 https://host/MyService.svc)连接到 WCF 服务时,就会发生这种情况。

切换到 https://host.mysite.com/MyService.svc就解决了这个问题。

一个单行解决方案。在客户端调用服务器之前在任何地方添加:

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

这只能用于测试目的,因为客户机将跳过 SSL/TLS 安全检查。

除了上面的答案之外,如果您的客户机运行的是错误的 TLS 版本,您可能会遇到此错误,例如,如果服务器只运行 TLS 1.2。

你可以用以下方法修复:

// tested in .NET 4.5:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

刚刚解决了一个类似的问题。

我意识到我有一个应用程序池,它运行在一个帐户之下,而这个帐户只对它所使用的证书具有读取权限。

NET 应用程序可以正确地检索证书,但只有在调用 GetRequestStream ()时才引发该异常。

证书权限可以通过 MMC 控制台管理

如果您使用.net core,请尝试以下操作:

client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication =
new X509ServiceCertificateAuthentication()
{
CertificateValidationMode = X509CertificateValidationMode.None,
RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck
};

如果你正在使用。Net 核心,然后在开发过程中可以通过使用编译器指令绕过证书验证。这种方法只验证发布的证书,而不验证调试的证书:

#if (DEBUG)
client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication =
new X509ServiceCertificateAuthentication()
{
CertificateValidationMode = X509CertificateValidationMode.None,
RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck
};   #endif

我只是想给@NMrt 的回答加点东西,他已经指出:

如果您的客户端运行错误的 TLS 版本,您可能会遇到此错误,例如,如果服务器只运行 TLS 1.2。

对于 Framework4.7.2,如果您没有像下面这样在 web.config 中显式地配置目标框架

<system.web>
<compilation targetFramework="4.7" />
<httpRuntime targetFramework="4.7" />
</system.web>

您的系统默认安全协议将被忽略,可能会使用“更低”的代替。在我的情况下,是 Ssl3/Tls 而不是 Tls13。

  • 您也可以通过设置 SecurityProtocol (保持其他协议正常工作)在代码中修复这个问题:

    System.Net.ServicePointManager.SecurityProtocol |= System.Net.SecurityProtocolType.Tls12 | System.Net.SecurityProtocolType.Tls11;
    System.Net.ServicePointManager.SecurityProtocol &= ~System.Net.SecurityProtocolType.Ssl3;
    
  • 甚至通过添加注册表项来启用或禁用强密码

    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319]
    "SchUseStrongCrypto"=dword:00000001
    

这篇博文为我指明了正确的方向,并且比我能做的更好地解释了背景:

Https://www.ryadel.com/en/asp-net-client-server-cannot-comunicate-because-they-possess-common-algorithm-how-to-fix-c-sharp/

为了帮助进行故障排除,您可以临时添加此信息,以记录导致验证失败的证书的其他信息。我把它记录到了 NLog 的 txt 日志中,但是如果你想的话,你可以创建 EventLog:

System.Net.ServicePointManager.ServerCertificateValidationCallback += (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) =>
{
StringBuilder sb = new StringBuilder();
sb.AppendLine($"  Certificate Subject: {certificate.Subject}");
sb.AppendLine($"  Certificate Issuer: {certificate.Issuer}");
sb.AppendLine($"  Certificate CertHash: {certificate.GetCertHashString()}");
sb.AppendLine($"  Certificate EffectiveDate: {certificate.GetEffectiveDateString()}");
sb.AppendLine($"  Certificate ExpirationDate: {certificate.GetExpirationDateString()}");
sb.AppendLine($"  sslPolicyErrors: {sslPolicyErrors.ToString()}");
sb.AppendLine($"  ChainPolicy:");
sb.AppendLine($"     Chain revocation flag: {chain.ChainPolicy.RevocationFlag}");
sb.AppendLine($"     Chain revocation mode: {chain.ChainPolicy.RevocationMode}");
sb.AppendLine($"     Chain verification flag: {chain.ChainPolicy.VerificationFlags}");
sb.AppendLine($"     Chain verification time: {chain.ChainPolicy.VerificationTime}");
sb.AppendLine($"     Chain status length: {chain.ChainStatus.Length}");
sb.AppendLine($"     Chain application policy count: {chain.ChainPolicy.ApplicationPolicy.Count}");
sb.AppendLine($"     Chain certificate policy count: {chain.ChainPolicy.CertificatePolicy.Count}");


sb.AppendLine($"  ChainStatus:");
foreach (var cs in chain.ChainStatus)
{
sb.AppendLine($"     Chain certificate policy count: Status: {cs.Status}, StatusInformation: {cs.StatusInformation}");
}


NLog.Common.InternalLogger.Error($"ServerCertificateValidationCallback: {sb}\n");


return true;
};