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

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

我们知道服务器没有有效的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。这会改变什么吗?


当前回答

我一整天都在为这个问题而挣扎。

当我用。net 4.5创建一个新项目时,我终于让它工作了。

但如果我降级到4.0,我又遇到了同样的问题,而且对于那个项目来说是不可逆转的(即使我试图再次升级到4.5)。

奇怪的是,没有其他错误消息,但“请求被中止:无法创建SSL/TLS安全通道。

其他回答

正如你所知道的,有很多原因可能会发生这种情况。我想我应该加上我遇到的原因…

如果你设置了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 ...

system.net.webeexception:请求被中止:无法创建 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

在我的例子中,运行应用程序的服务帐户没有访问私钥的权限。一旦我给予了这个许可,错误就消失了

mmc 证书 扩展到个人 选择证书 右击 所有任务 管理私钥 添加业务帐户用户

对于SOAP/WCF用户,当服务器拒绝您的WS-Security配置时,也会发生此错误。客户端接收到的错误信息非常模糊,但是服务器管理员可能能够确定原因。

UsernameToken配置文件下有一个这样的例子,其中消息被<wsu:Created> time视为过期,不是有效的ISO 8601 datetime,原因可能是格式错误、不是UTC或服务器时间不匹配。

<wsse:UsernameToken wsu:Id="Example-1">
   <wsse:Username> ... </wsse:Username>
   <wsse:Password Type="..."> ... </wsse:Password>
   <wsse:Nonce EncodingType="..."> ... </wsse:Nonce>
   <wsu:Created>2021-01-31T19:00:00.0000000Z</wsu:Created>
</wsse:UsernameToken>

设置方法

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12

看起来还可以,因为Tls1.2是最新版本的安全协议。但我决定深入研究,并回答我们是否真的需要硬编码它。

规格:Windows Server 2012R2 x64。

从互联网上得知,. net framework 4.6+必须默认使用Tls1.2。但是当我把我的项目更新到4.6时,什么都没有发生。 我找到了一些信息,告诉我需要手动做一些更改,默认启用Tls1.2

https://support.microsoft.com/en-in/help/3140245/update-to-enable-tls-1-1-and-tls-1-2-as-default-secure-protocols-in-wi

但是建议的windows更新不适用于R2版本

但是帮助我的是在注册表中添加2个值。您可以使用下一个PS脚本,这样它们就会自动添加

Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord

这正是我想要的。但是我仍然不能回答为什么NetFramework 4.6+没有设置这个问题…自动协议值?