当前位置:  开发笔记 > 编程语言 > 正文

WebRequest错误 - 无法创建SSL/TLS安全通道

如何解决《WebRequest错误-无法创建SSL/TLS安全通道》经验,为你挑选了0个好方法。

我正在尝试编写C#代码,该代码针对用于计算Web应用程序中的销售税的REST服务端点发出Web请求.这是第三方服务,使用SSL进行保护.有两种环境,UAT和生产.运行webrequest的代码如下所示:

...

var req = WebRequest.Create(url) as HttpWebRequest;
req.Method = "POST";
req.ContentType = "application/json";

...

using (var webresponse = req.GetResponse())
{
    using (var responseStream = new StreamReader(webresponse.GetResponseStream()))
    {
        var respJson = responseStream.ReadToEnd();
        calcResult = BuildResponse(calcRequest, respJson, consoleWriteRawReqResponse);
    }
}

return calcResult;

这对UAT环境很好.但是当我在生产环境中运行相同的代码时,我收到错误:

"无法创建SSL/TLS安全通道"

能没有问题,从邮差执行这两个请求,没有任何特殊的修改.

这导致我走上了调查这个错误的道路,我找到了很多有用的SO帖子来讨论这个话题,包括:

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

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

这些帮助指向了我正确的方向,即查看将ServicePointManager.SecurityProtocol设置设置为不同的值,并使用ServicePointManager.ServerCertificateValidationCallback来调查错误.

我玩这些后发现的是以下内容:

UAT环境调用将使用Ssl3 |的默认设置 Tls(.NET 4.5.2的默认值),而生产环境则不会.

只有当我将此设置显式设置为Ssl3时,生产调用才会起作用.

该代码如下所示:

...

var req = WebRequest.Create(url) as HttpWebRequest;
req.Method = "POST";
req.ContentType = "application/json";

...

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CertValidationCallback);
using (var webresponse = req.GetResponse())
{
    using (var responseStream = new StreamReader(webresponse.GetResponseStream()))
    {
        var respJson = responseStream.ReadToEnd();
        calcResult = BuildResponse(calcRequest, respJson, consoleWriteRawReqResponse);
    }
}
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls;

return calcResult;

这尤其令人困惑,因为在查看Web浏览器中的端点时,我可以看到它们都受到相同通配符证书的保护,并且都使用TLS 1.0.

所以我希望将ServicePointManager.SecurityProtocol设置为TLS可以正常工作,但事实并非如此.

我真的想避免将ServicePointManager.SecurityProtocol显式设置为SSL3,因为我们的应用程序是一个Web应用程序,并且有多个其他通过SSL进行通信的集成点.这些都很好,我不想对它们的功能产生负面影响.即使我在调用之前设置了此设置,然后立即将其更改回来,我也存在遇到并发问题的风险,因为ServicePointManager.SecurityProtocol是静态的.

我也调查了这个话题,并不喜欢我读的内容.有提及使用不同的应用程序域:

.NET https跨线程使用不同安全协议的请求

如何在特定的HttpWebRequest中使用SSL3而不是TLS?

但这对我来说似乎过于复杂/苛刻.处理创建应用程序域真的是唯一的解决方案吗?或者这是我不应该试图解决的问题,而是与相关服务的所有者一起讨论?我非常好奇它可以在一个环境/服务器上使用TLS,但不能在另一个环境/服务器上使用.

编辑 我做了更多的玩这个.我更改了我的客户端以使用此博客文章中概述的方法(使用不同的应用程序域来隔离更改ServicePointManager.SecurityProtocol的代码):

https://bitlush.com/blog/executing-code-in-a-separate-application-domain-using-c-sharp

这实际上运作得很好,可能是后退解决方案.但我也了解到有问题的服务提供商有一个使用TLS 1.2保护的不同端点(相同的URL,不同的端口).值得庆幸的是,通过在global.asax.cs应用程序启动事件中扩展我的SecurityProtocol设置:

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

我能够在所有环境中与服务进行良好的沟通.它也不会影响我现有的与其他服务的集成(例如,Cyber​​Source).

但是 - 现在有一个新的但相关的问题.如果我如上所述扩展SecurityProtocolType,为什么这个调用才有效?我的其他集成,如Cyber​​Source,并不需要这样.但是这个确实如此.并且它们似乎都是使用我在浏览器中看到的TLS 1.2来保护的.

推荐阅读
mobiledu2402852357
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有