我有一个使用 HTTPS 在 IIS 7 中托管的 WCF 服务。当我在 Internet Explorer 中浏览到这个站点时,它就像一个魅力,这是因为我已将证书添加到本地根证书颁发机构存储中。
我正在一台机器上开发,所以客户端和服务器是同一台机器。证书是直接从 IIS 7 管理单元中自签名的。
我现在不断收到此错误...
无法为具有权限的 SSL/TLS 安全通道建立信任关系。
...从客户端控制台调用时。
我使用 findprivatekey
和 cacls.exe
手动为自己授予证书的权限和网络服务。
我尝试使用 SOAPUI 连接到服务,并且可以正常工作,因此它一定是我的客户端应用程序中的一个问题,它是基于过去使用 http 的代码。
我还能在哪里看我似乎已经用尽了所有可能性,为什么我无法连接?
作为一种解决方法,您可以在客户端向 ServicePointManager
的 ServerCertificateValidationCallback
添加一个处理程序:
System.Net.ServicePointManager.ServerCertificateValidationCallback +=
(se, cert, chain, sslerror) =>
{
return true;
};
但请注意,这不是一个好的做法,因为它完全忽略了服务器证书并告诉服务点管理器任何证书都可以,这可能会严重危及客户端安全。您可以对此进行改进并进行一些自定义检查(针对证书名称、哈希等)。至少可以在使用测试证书时规避开发过程中出现的问题。
当我遇到这个问题时,这是因为 client.config 的端点如下:
https://myserver/myservice.svc
但证书是期待的
https://myserver.mydomain.com/myservice.svc
更改端点以匹配服务器的 FQDN 解决了我的问题。我知道这不是这个问题的唯一原因。
出现问题是因为您使用的是自签名密钥。客户端不信任此密钥,密钥本身也不提供验证链或证书吊销列表。
你有几个选择 - 你可以
关闭客户端上的证书验证(糟糕的举动,中间人攻击比比皆是)使用 makecert 创建根 CA 并从中创建证书(好的移动,但仍然没有 CRL)使用 Windows 证书服务器创建内部根 CA或其他 PKI 解决方案然后信任该根证书(管理起来有点麻烦)从一个受信任的 CA 购买 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;
}
单线解决方案。在客户端调用服务器之前添加这个:
System.Net.ServicePointManager.ServerCertificateValidationCallback += delegate { return true; };
这应该只用于测试目的,因为客户端将跳过 SSL/TLS 安全检查。
我遇到了同样的问题,我可以通过两种解决方案解决它:首先,我使用 MMC 管理单元“证书”作为“计算机帐户”并将自签名证书拖到“受信任的根证书颁发机构”文件夹中.这意味着本地计算机(生成证书的计算机)现在将信任该证书。其次,我注意到证书是为某些内部计算机名称生成的,但是正在使用另一个名称访问 Web 服务。这在验证证书时导致不匹配。我们为 computer.operations.local 生成了证书,但使用 https://computer.internaldomain.companydomain.com 访问了 Web 服务。当我们将 URL 切换到用于生成证书的 URL 时,我们不再出现错误。
也许只是切换 URL 就可以了,但是通过使证书受信任,您还可以避免 Internet Explorer 中的红屏,它告诉您它不信任证书。
如果你使用 .net core 试试这个:
client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication =
new X509ServiceCertificateAuthentication()
{
CertificateValidationMode = X509CertificateValidationMode.None,
RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck
};
请执行以下步骤:
在 IE 中打开服务链接。单击地址栏中提及的证书错误,然后单击查看证书。支票发给:姓名。获取发布的名称并将服务和客户端端点基地址名称中提及的 localhost 替换为完全限定的域名 (FQDN)。
例如: https://localhost:203/SampleService.svc 到 https://INL-126166-.groupinfra.com:203/SampleService.svc
除了上面的答案之外,如果您的客户端运行错误的 TLS 版本,例如如果服务器仅运行 TLS 1.2,您可能会遇到此错误。
您可以使用以下方法修复它:
// tested in .NET 4.5:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
我有同样的问题。我还在本地商店中添加了 CA 证书,但我做错了。
使用 mmc 控制台(开始 -> 运行 -> mmc )您应该将证书管理单元添加为服务帐户(选择 IIS 的服务帐户)或计算机帐户(它为机器上的每个帐户添加)
https://i.stack.imgur.com/hemGc.png
从现在开始,您可以添加 CA(受信任的根 CA 和中间 CA)的证书,一切正常
我对自签名证书有类似的问题。我可以通过使用与服务器的 FQDN 相同的证书名称来解决它。
理想情况下,SSL 部分应在服务器端进行管理。客户端不需要为 SSL 安装任何证书。此外,还提到了一些关于从客户端代码绕过 SSL 的帖子。但我完全不同意这一点。
我只是将证书拖到“受信任的根证书颁发机构”文件夹中,瞧一切正常。
哦。我首先从管理员命令提示符中添加了以下内容:
netsh http add urlacl url=https://+:8732/Servicename user=NT-MYNDIGHET\INTERAKTIV
我不确定您需要的用户名称(如您所见,我的是挪威语!):user=NT-AUTHORITY/INTERACTIVE
?
您可以通过发出以下命令查看所有现有的 urlacl:netsh http show urlacl
我只是想在@NMrt 已经指出的答案中添加一些内容:
如果您的客户端运行错误的 TLS 版本,您可能会遇到此错误,例如,如果服务器仅运行 TLS 1.2。
对于 Framework 4.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
这篇博文为我指明了正确的方向,并比我更好地解释了背景:
尝试通过连接到 WCF 服务时发生这种情况。 IP 例如 https://111.11.111.1:port/MyService.svc
,同时使用与名称绑定的证书,例如 mysite.com。
切换到 https://mysite.com:port/MyService.svc
解决了它。
这发生在尝试仅使用主机名(例如 https://host/MyService.svc)连接到 WCF 服务,同时使用与名称绑定的证书(例如 host.mysite.com)。
切换到 https://host.mysite.com/MyService.svc 并解决了它。
刚刚修复了一个类似的问题。
我意识到我有一个应用程序池,该应用程序池在一个帐户下运行,该帐户仅对所使用的证书具有读取权限。
.NET 应用程序可以正确检索证书,但只有在调用 GetRequestStream() 时才会引发该异常。
可以通过 MMC console 管理证书权限
如果您使用的是 .net 核心,那么在开发期间您可以使用编译器指令绕过证书验证。这种方式只会验证证书的发布而不是调试:
#if (DEBUG)
client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication =
new X509ServiceCertificateAuthentication()
{
CertificateValidationMode = X509CertificateValidationMode.None,
RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck
}; #endif
为了帮助进行故障排除,您可以临时添加它以记录有关导致验证失败的证书的其他信息。我将它记录到 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;
};
将此添加到您的客户端代码中:
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(
delegate
{
return true;
});