尽管设置了 ServerCertificateValidationCallback,仍无法创建 SSL/TLS 安全通道

问题描述 投票:0回答:10

我正在尝试使用自签名证书建立与测试服务器的 SSL/TLS 连接。通过不安全通道的通信没有出现任何问题。

这是我的示例代码,是我根据此解决方案编写的:

允许使用 HttpClient 不受信任的 SSL 证书 C# 忽略证书错误? .NET 客户端连接到 ssl Web API

ServicePointManager.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true; var c = new HttpClient(); var r = c.GetAsync("https://10.3.0.1:8443/rest/v1").Result; if (r.IsSuccessStatusCode) { Log.AddMessage(r.Content.Get<string>()); } else { Log.AddMessage(string.Format("{0} ({1})", (int)r.StatusCode, r.ReasonPhrase)); }

也尝试过这个:

var handler = new WebRequestHandler(); handler.ServerCertificateValidationCallback = delegate { return true; }; var c = new HttpClient(handler); ...

还有这个

ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };

但每次我都会遇到例外:

InnerException: System.Net.Http.HttpRequestException _HResult=-2146233088 _message=An error occurred while sending the request. HResult=-2146233088 IsTransient=false Message=An error occurred while sending the request. InnerException: System.Net.WebException _HResult=-2146233079 _message=The request was aborted: Could not create SSL/TLS secure channel. HResult=-2146233079 IsTransient=false Message=The request was aborted: Could not create SSL/TLS secure channel. Source=System StackTrace: at System.Net.HttpWebRequest.EndGetResponse(IAsyncResult asyncResult) at System.Net.Http.HttpClientHandler.GetResponseCallback(IAsyncResult ar) InnerException:

我做错了什么?为什么我无法连接到该服务器(其具有无效的自签名证书)

c# ssl https
10个回答
200
投票
您使用 ServerCertificateValidationCallback 做得正确。这不是您面临的问题。您面临的问题很可能是 SSL/TLS 协议的版本。

例如,如果您的服务器仅提供 SSLv3 和 TLSv10,而您的客户端需要 TLSv12,那么您将收到此错误消息。您需要做的是确保客户端和服务器都支持通用协议版本。

当我需要一个能够连接到尽可能多的服务器(而不是尽可能安全)的客户端时,我使用它(与设置验证回调一起):

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
    

34
投票
我们今天一直在解决同样的问题,你需要做的就是增加.NET的运行时版本

4.5.2 对我们遇到上述问题不起作用,而 4.6.1 还可以

如果需要保留.NET版本,则设置

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;
    

18
投票
作为对仍然遇到此问题的任何人的后续行动 - 我添加了 ServicePointManager.SecurityProfile 选项,如解决方案中所述:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12;

但我仍然收到相同的“请求已中止:无法创建 SSL/TLS 安全通道”错误。我尝试使用 HTTPS SOAP API 接口连接到一些较旧的语音服务器(即多年前安装的语音邮件、IP 电话系统等)。这些仅支持 SSL3 连接,因为它们上次更新是在几年前。

有人可能认为将 SSl3 包含在安全协议列表中就可以解决问题,但事实并非如此。我强制连接的唯一方法是仅包含 Ssl3 协议而不包含其他协议:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

然后连接就通过了——对我来说似乎是一个错误,但直到最近我为这些服务器提供的工具才开始抛出错误,这些工具已经存在多年了——我相信微软已经开始推出已经更新的系统更改除非没有其他选择,否则此行为会强制 TLS 连接。

无论如何 - 如果您仍然在某些旧站点/服务器上遇到此问题,那么值得一试。


6
投票
移动此行:ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 |安全协议类型.Tls |安全协议类型.Tls11 |安全协议类型.Tls12;

此行之前:HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);

原帖:

KB4344167 安全更新破坏了 TLS 代码


6
投票
我正在使用 .NET 版本 4.8 并在 HttpClient 初始化期间指定 SSL 协议,这有助于我解决此问题,如下所示。

var client = new HttpClient(new HttpClientHandler { SslProtocols = SslProtocols.Tls12});
    

2
投票
在我的例子中,客户端和服务器上都启用了 TLS1_2,但服务器使用 MD5,而客户端禁用它。因此,请在

http://ssllabs.com 上测试客户端和服务器,或使用 openssl/s_client 进行测试,看看发生了什么。另外,使用 Wireshark 检查所选密码。


1
投票
TLS 1.0 和 1.1 现已终止生命周期。我们的亚马逊网络服务器上的一个包更新了,我们开始收到此错误。

答案在上面,但你不应该再使用

tls

tls11
了。

特别是对于 ASP.Net,请将其添加到您的启动方法之一。

public Startup() { ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12;

但我确信类似的方法在许多其他情况下也适用。


0
投票
我遇到了这个线程,因为我也遇到了错误

无法创建 SSL/TLS 安全通道。在我的例子中,我尝试使用 Invoke-RestMethod

 从 PowerShell 访问 Siebel 配置 REST API,但上面的建议都没有帮助了。 

最终我偶然发现了问题的原因:我联系的服务器需要客户端证书身份验证。

为了使通话正常进行,我必须提供带有

-Certificate

 参数的客户端证书(包括私钥):

$Pwd = 'certificatepassword' $Pfx = New-Object -TypeName 'System.Security.Cryptography.X509Certificates.X509Certificate2' $Pfx.Import('clientcert.p12', $Pwd, 'Exportable,PersistKeySet') Invoke-RestMethod -Uri 'https://your.rest.host/api/' -Certificate $Pfx -OtherParam ...

希望我的经验可以帮助其他对这个问题有特殊看法的人。


0
投票
如果您在安全协议中仅指定 TLS,则效果会很完美。

try { ServicePointManager.Expect100Continue = true; ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; var webClient = new WebClient(); var s = webClient.DownloadString("https://google.com"); Console.WriteLine(s); } catch (Exception ex) { Console.WriteLine(ex); } Console.ReadLine();
    

0
投票
如果您使用.net Framework 4.0,请使用以下行

ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;

© www.soinside.com 2019 - 2024. All rights reserved.