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

716

由于以下错误信息,我们无法使用WebRequest连接到HTTPS服务器:

The request was aborted: Could not create SSL/TLS secure channel.

我们知道服务器在所使用的路径上没有有效的HTTPS证书,但为了绕过这个问题,我们使用从另一个StackOverflow帖子中获取的以下代码:

private void Somewhere() {
    ServicePointManager.ServerCertificateValidationCallback += new RemoteCertificateValidationCallback(AlwaysGoodCertificate);
}

private static bool AlwaysGoodCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors policyErrors) {
   return true;
}

问题在于服务器从未验证证书,因此出现上述错误。有人知道我该怎么做吗?


我应该提到,几周前我和一位同事进行了测试,并且使用类似我上面写的东西正常工作。我们发现唯一的“主要区别”是我使用的是Windows 7,而他使用的是Windows XP。这会改变什么吗?


4
也请查看这个链接 https://dev59.com/I3I-5IYBdhLWcg3w8dYQ - Oskar Kjellin
135
到了2018年,这个问题已经被查看了308,056次,但仍然没有适当的解决方法!!我会随机遇到这个问题,这里或其他线程提到的任何修复措施都不能解决我的问题。 - Nigel Fds
7
@NigelFds 错误The request was aborted: Could not create SSL/TLS secure channel是一个非常通用的错误。它基本上表示“由于许多可能的原因之一,SSL/TLS/HTTPS连接初始化失败”。因此,如果您在特定情况下经常遇到这个错误,最好的选择是提出一个具体的问题,并提供有关该情况的具体细节。同时,检查事件查看器以获取更多信息。另外,启用一些.NET客户端调试以获取更多详细信息(例如服务器证书是否不受信任?是否存在密码匹配问题?SSL/TLS协议版本不匹配等)。 - MarnixKlooster ReinstateMonica
6
@MarnixKlooster,我已经检查了所有内容,证书不可能是问题,因为如果我重试它,它就可以工作。我怀疑如果我在 SO 上提出这个问题,没有人会标记它为重复或其他什么。 - Nigel Fds
5
使用4.5.2几乎肯定是问题的主要原因。运行时确定安全协议的默认设置,而4.5.x只启用了SSL 3.0和TLS 1.0,这意味着如果您的应用程序调用了一个已禁用TLS 1.0的API,它将无法工作。尝试使用更高版本的.NET Framework,最好是4.7或更高版本。请参见我的答案获取更多详细信息,特别是如果您的应用程序是ASP.NET站点。 - JLRishe
显示剩余14条评论
51个回答

10

你可以看出这可能发生的原因很多。我想补充一下我遇到的原因...

如果你把 WebRequest.Timeout 的值设为 0,就会抛出这个异常。以下是我遇到的代码...(除了超时值的硬编码 0 之外,我有一个参数意外地设为了 0)。

WebRequest webRequest = WebRequest.Create(@"https://myservice/path");
webRequest.ContentType = "text/html";
webRequest.Method = "POST";
string body = "...";
byte[] bytes = Encoding.ASCII.GetBytes(body);
webRequest.ContentLength = bytes.Length;
var os = webRequest.GetRequestStream();
os.Write(bytes, 0, bytes.Length);
os.Close();
webRequest.Timeout = 0; //setting the timeout to 0 causes the request to fail
WebResponse webResponse = webRequest.GetResponse(); //Exception thrown here ...

2
哇!感谢提到这个。一开始不敢相信,试了很多不同的方法。最后将超时设置为10秒,异常就消失了!这对我来说是解决方案。(y) - derFunk

8

System.Net.WebException: 请求被中止:无法创建 SSL/TLS 安全信道。

在我们的情况下,我们使用的是软件供应商,因此我们无法访问修改 .NET 代码。显然,除非有更改,否则 .NET 4 不会使用 TLS v 1.2。

我们的解决方法是将 SchUseStrongCrypto 键添加到注册表中。您可以将以下代码复制/粘贴到带有 .reg 扩展名的文本文件中并执行它。它作为我们的“补丁”解决了这个问题。

Windows Registry Editor Version 5.00

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

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

3
这里是用于快速编辑的PS命令:New-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\.NETFramework\v4.0.30319" -Name "SchUseStrongCrypto" -Value "1" -Type DWord。该命令的作用是在注册表中添加一个名为"SchUseStrongCrypto"、数值类型为DWord、数值为1的键值对,路径为"HKLM:\SOFTWARE\Microsoft.NETFramework\v4.0.30319"。 - Tilo
2
PS 快速编辑2:New-ItemProperty -Path "HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319" -Name "SchUseStrongCrypto" -Value "1" -Type DWord - Tilo
这最终成为了我们的问题和解决方案。我们在运行.NET Framework v4.8的Windows 2012服务器上运行的应用程序,每当向数据中心内的其他Windows 2016服务器进行HTTPS请求时,就会出现SSL错误。将这些注册表编辑应用于_2012_主机后,问题得到了解决。以下是一个有关此的有用文章: 为所有.NET应用程序启用强加密- JohnLouros.com - Daniel Knowlton

8
如果您正在从Visual Studio运行代码,请尝试以管理员身份运行Visual Studio。这对我解决了问题。

1
这可能意味着您在运行的用户帐户中没有访问证书或私钥的权限。 - Ed Bayiates

7
我整天都在为这个问题苦恼。
当我用.NET 4.5创建一个新项目时,最终解决了它。
但是,如果我降级到4.0,我再次遇到了同样的问题,并且对于该项目来说是不可逆转的(即使我再次尝试升级到4.5)。
奇怪的是,这个错误没有其他错误消息,只有"请求中止:无法创建SSL / TLS安全通道"。

5
这样做起作用的原因可能是不同版本的.NET支持不同的SSL/TLS协议版本。更多信息请参考:http://blogs.perficient.com/microsoft/2016/04/tsl-1-2-and-net-support/ - Jon Schneider
我认为这篇文章有助于解释为什么升级可以解决你的问题。https://johnlouros.com/blog/enabling-strong-cryptography-for-all-dot-net-applications - Daniel Knowlton

7
如果客户端是Windows机器,可能的原因是服务所需的TLS或SSL协议未被激活。您可以在以下位置进行设置:控制面板->网络和Internet->Internet选项->高级。滚动设置到“安全”并在以下选项中选择: - 使用SSL 2.0 - 使用SSL 3.0 - 使用TLS 1.0 - 使用TLS 1.1 - 使用TLS 1.2

enter image description here


全部勾选会有任何问题吗? - Nigel Fds
没有问题,就我所知...除了 SSL 不再被推荐使用...它们不被认为足够安全。 - cnom
如何在PowerShell中以编程方式实现? - Kiquenet
这是影响旧版Windows的问题,请进行一些研究,了解当前正在使用的安全选项。截至今天,请参阅此链接:https://tecadmin.net/enable-tls-on-windows-server-and-iis/ - Tod

7

对我来说,所有这些答案都不起作用,Google Chrome和Postman可以工作并与服务器进行握手,但IE和.NET却不能。在Google Chrome的安全选项卡中,连接显示使用ECDHE_RSA with P-256 and AES_256_GCM密码套件进行加密和身份验证来与服务器进行握手。

在此输入图片描述

我安装了IIS Crypto,在Windows Server 2012 R2的密码套件列表中找不到ECDHE_RSA with P-256 and AES_256_GCM密码套件。然后我将Windows更新到最新版本,但问题没有解决。最终,在搜索之后,我了解到Windows Server 2012 R2无法正确支持GSM,于是我将服务器升级到Windows Server 2016,我的问题得到解决。


6
另一种可能性是正在执行的代码缺少所需的权限。
在我的情况下,当我使用Visual Studio调试器测试对Web服务的调用时,出现了这个错误。由于Visual Studio没有以管理员身份运行,这导致了这个异常。

5
我遇到了同样的问题,发现这个答案对我很有帮助。关键点是3072。这个链接提供了“3072”修复的详细信息。
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;

XmlReader r = XmlReader.Create(url);
SyndicationFeed albums = SyndicationFeed.Load(r);

在我的情况下,需要修复两个源:

https://www.fbi.gov/feeds/fbi-in-the-news/atom.xml
https://www.wired.com/feed/category/gear/latest/rss

即使您使用古老的4.0 .NET框架,此解决方案也能正常工作。 - Antti

5

对我都没有用,以下方法是有效的:

初始化我的X509Certificate2时,不要使用以下方式:

   var certificate = new X509Certificate2(bytes, pass);

我是这样做的:
   var certificate = new X509Certificate2(bytes, pass, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);

注意X509KeyStorageFlags.Exportable!!

我没有改变代码的其他部分(WebRequest本身):

// I'm not even sure the first two lines are necessary:
ServicePointManager.Expect100Continue = true; 
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

request = (HttpWebRequest)WebRequest.Create(string.Format("https://{0}.sii.cl/cvc_cgi/dte/of_solicita_folios", server));
request.Method = "GET";
request.Referer = string.Format("https://hercules.sii.cl/cgi_AUT2000/autInicio.cgi?referencia=https://{0}.sii.cl/cvc_cgi/dte/of_solicita_folios", servidor);
request.UserAgent = "Mozilla/4.0";
request.ClientCertificates.Add(certificate);
request.CookieContainer = new CookieContainer();

using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
    // etc...
}

实际上,我甚至不确定前两行是否必要...

在我的情况下,只有在将进程托管在IIS中(即Web应用程序调用其他地方)时才会出现此问题。- 这解决了问题!感谢分享! - Efrain
使用这行代码 ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; 对我很有效。 - Atiq Baqi

4

大多数上面的回答提到了会话算法或密钥交换算法。

在我的情况下,两者都没问题,问题出在服务器证书哈希算法上,在客户端电脑上没有启用。

我通过添加一个部分到我的应用程序配置中解决了这个问题。

<system.diagnostics>
    <trace autoflush="true" />
    <sources>
        <source name="System.Net">
            <listeners>
                <add name="System.Net" />
            </listeners>
        </source>
        <source name="System.Net.Sockets">
            <listeners>
                <add name="System.Net" />
            </listeners>
        </source>
        <source name="System.Net.Cache">
            <listeners>
                <add name="System.Net" />
            </listeners>
        </source>
    </sources>
    <sharedListeners>
        <add
            name="System.Net"
            type="System.Diagnostics.TextWriterTraceListener"
            initializeData="System.Net.trace.log"
        />
    </sharedListeners>
    <switches>
        <add name="System.Net" value="Verbose" />
        <add name="System.Net.Sockets" value="Verbose" />
        <add name="System.Net.Cache" value="Verbose" />
    </switches>
</system.diagnostics>

然后日志中的错误引导我到了这个解决方案


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