请求已中止:无法创建SSL/TLS安全通道。

84

我的客户告诉我他们在使用Internet Explorer访问URL时遇到了SSL问题。他们说他们遇到了信任问题。

我正在通过HTTPS访问JSON。网站位于一个服务器上,我正在使用本地机器上的控制台应用程序。我尝试绕过SSL证书,但是我的代码仍然失败。

我可以修改HttpWebRequest来解决这个问题吗?

我在使用这段代码时遇到了以下错误:

    // You must change the URL to point to your Web server.
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
        req.Method = "GET";
        req.AllowAutoRedirect = true;

        // allows for validation of SSL conversations
        ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };


        WebResponse respon = req.GetResponse();
        Stream res = respon.GetResponseStream();

        string ret = "";
        byte[] buffer = new byte[1048];
        int read = 0;
        while ((read = res.Read(buffer, 0, buffer.Length)) > 0)
        {
            //Console.Write(Encoding.ASCII.GetString(buffer, 0, read));
            ret += Encoding.ASCII.GetString(buffer, 0, read);
        }
        return ret;

请求被中止:无法创建SSL/TLS安全通道

你是否在使用自签名证书? - Carsten Schütte
不,客户说的是Comodo。 - Joseph Anderson
可能是The request was aborted: Could not create SSL/TLS secure channel的重复问题。 - Chris Moschini
15个回答

164

我不得不启用其他安全协议版本来解决此问题:

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

很好知道可以像枚举一样设置多个值。 - Nicholas Petersen
2
@NicholasPetersen 提醒您,只有带有 Flags 属性的枚举才能实现此操作。请参阅 https://msdn.microsoft.com/zh-cn/library/system.flagsattribute(v=vs.110).aspx。 - defines
ASP.NET 开发人员 - 将以下代码添加到您的 Global.asax.cs 文件中,一般位于 App_code 文件夹中的 Application_Start 方法和适当的命名空间中。效果非常好。这个错误是在 Windows .NET 2018 年 3 月安全更新后开始出现的。 - moto_geek
如果服务器端只接受带有SHA256或SHA384哈希的密码,那么这并没有什么帮助。 - Libor B.
我宁愿升级到 .net 4.8 或更高版本 - 但对于那些无法升级或临时的地方,这是一个好主意。例如,SSIS 是一个我无法轻松升级的地方,而 regedit 似乎是微软的“解决方案”。 - Richard Housham
显示剩余5条评论

29

我使用了这段代码启用了日志记录:

http://blogs.msdn.com/b/dgorti/archive/2005/09/18/471003.aspx

日志位于 bin/debug 文件夹中(我在控制台应用程序的调试模式下)。 您需要将安全协议类型添加为SSL 3。

我在日志中收到了算法不匹配的消息。 这是我的新代码:

        // You must change the URL to point to your Web server.
        HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
        req.Method = "GET";
        ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;


        // Skip validation of SSL/TLS certificate
        ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };


        WebResponse respon = req.GetResponse();
        Stream res = respon.GetResponseStream();

        string ret = "";
        byte[] buffer = new byte[1048];
        int read = 0;
        while ((read = res.Read(buffer, 0, buffer.Length)) > 0)
        {
            Console.Write(Encoding.ASCII.GetString(buffer, 0, read));
            ret += Encoding.ASCII.GetString(buffer, 0, read);
        }
        return ret;

9
需要提到的是,在SSLv3上发现了一个漏洞(http://security.stackexchange.com/a/70724),因此大多数实现已停止使用它。您应该使用“SecurityProtocolType.Tls12”而不是SSLv3。 - douglaslps
12
请注意,使用此解决方案意味着将接受任何服务器证书作为有效证书(因为“ServerCertificateValidationCallback”始终返回true)。 - Aurélien Gasser
使用 Method = "HEAD" 进行故障排除? - Kiquenet

15

现有答案类似,但使用PowerShell:

[System.Net.ServicePointManager]::SecurityProtocol = `
[System.Net.SecurityProtocolType]::Tls11 -bor 
[System.Net.SecurityProtocolType]::Tls12 -bor `   
[System.Net.SecurityProtocolType]::Tls -bor `
[System.Net.SecurityProtocolType]::Ssl3

那么调用Invoke-WebRequest应该可以工作。

这是从匿名反馈中得到的,是个好建议: 更简单的写法是:

[System.Net.ServicePointManager]::SecurityProtocol = @("Tls12","Tls11","Tls","Ssl3")

发现了Jaykul的这篇精彩相关文章:从 .Net 和 PowerShell 验证自签名证书


答案根据排序方式和默认的投票数量而移动。考虑通过作者来引用其他答案。 - Litty
谢谢您的帖子...我曾经困惑于如何设置协议类型。 - Thom Schumacher

7
这可能是由几个原因引起的(从最可能到最不可能):
  1. 客户端不信任服务器的SSL证书。最简单的检查方法是在URL上使用浏览器,看是否获得了SSL锁定图标。如果您得到了一个损坏的锁定图标,请单击它以查看问题所在:

    1. 过期日期-获取新的SSL证书
    2. 名称不匹配-确保您的URL使用与证书相同的服务器名称。
    3. 未经受信任机构签署-从类似于Verisign的机构购买证书,或将证书添加到客户端的受信任证书存储中。
    4. 在测试环境中,您可以更新证书验证器以跳过访问检查。但是,在生产中不要这样做。
  2. 服务器需要客户端SSL证书-在这种情况下,您必须更新代码以使用客户端证书对请求进行签名。


2
除了最后一点外,一切都很好。客户端证书不用于签署请求,而是在握手中提供,因此需要在打开连接之前将其提供给传输层。如何在Javascript中完成这项任务留给读者自己练习。;-) - user207421
我如何使用客户端证书进行签名?我添加了ServicePointManager.ServerCertificateValidationCallback = delegate { return true; },但仍然出现错误。 - Joseph Anderson
你的评论“需要客户端 SSL 证书”帮助我查看了我发送的实际证书......因此,现在我的新答案就是这个问题。现在是“duh”时刻,但几个小时前不是!谢谢 - granadaCoder

6

我注意到,在创建 HttpWebRequest 对象之前将 ServicePointManager.SecurityProtocol 的值设置为 (SecurityProtocolType)3072 可以帮助解决 .Net v4.0 中的问题。


感谢提醒我在创建HttpWebRequest对象之前设置SecurityProtocol。但是...为什么要将int强制转换而不是拼写出枚举值呢? - Nathan
或者直接使用System.Net中的枚举值SecurityProtocolType.Tls12。 - Mark A. Durham
以上建议对我有用。该解决方案应该被接受。您可以在评论部分下面找到我的代码行。 - Sangamesh Arali

4
同样收到了“无法创建SSL/TLS安全信道”的错误。以下是对我有效的解决方法。 System.Net.ServicePointManager.SecurityProtocol = (System.Net.SecurityProtocolType)3072;

2

很遗憾,以上提到的答案都对我没用。下面列出的代码对我非常有用。如果有人需要帮助的话,可以试试。

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

在创建HttpWebRequest之前,必须进行此设置。


1
主要是在创建HttpWebRequest之前进行设置。谢谢。 - persec10000

2

来自@sameerfair的评论

“对于.Net v4.0,我注意到在创建HttpWebRequest对象之前将ServicePointManager.SecurityProtocol的值设置为(SecurityProtocolType)3072有所帮助。”

上述建议对我起作用了。以下是我的代码行,它们对我起作用:

var securedwebserviceurl="https://somedomain.com/service";
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11;
// Skip validation of SSL/TLS certificate
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
var httpWebRequest = (HttpWebRequest)WebRequest.Create(securedwebserviceurl);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "POST";
httpWebRequest.ProtocolVersion= HttpVersion.Version10;
var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream())) {
string responseFromServer = streamReader.ReadToEnd();
}

1

这个问题已经超过2年了,我相信他们现在已经意识到SSL3是不安全的。 - user692942

1

将安全协议定义如下。在我的情况下,这解决了问题。

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接