安全通道支持中发生错误 - 经典 ASP HTTP 请求
Posted
技术标签:
【中文标题】安全通道支持中发生错误 - 经典 ASP HTTP 请求【英文标题】:An error occurred in the secure channel support - Classic ASP HTTP Request 【发布时间】:2014-01-25 19:10:36 【问题描述】:我有一个在 Windows Server 2012 机器上运行的经典 ASP 网站。一个页面使用如下代码通过 https 向另一个应用程序发出 HTTP 请求:
Sub ShopXML4http(url, inStr, outStr, method, xmlerror)
Dim objhttp
Set objhttp = Server.CreateObject ("MSXML2.ServerXMLHTTP.6.0")
objHttp.open method, url, false
If Method="POST" Then
objHttp.Send instr
Else
objHttp.Send
End if
outstr=objHttp.responseText
Set objhttp=nothing
End Sub
这段代码几乎在所有时间都可以正常工作(每天有数千个请求),但偶尔它会失败并显示如下消息:
号码:-2147012739
说明:安全通道支持发生错误
来源:msxml6.dll
该应用程序最近从旧的 Windows 2003 Server 移到了 2012 Server,而这个问题似乎从来不是旧服务器上的问题。此外,虽然网站上发生了这个错误,但我可以在 VBScript 中运行完全相同的代码,它工作正常。重置应用程序池似乎使站点能够再次执行安全 HTTP 请求(尽管它经常在我到达服务器之前自行修复)。
【问题讨论】:
我能够验证在同一个应用程序池中,我能够在 ASP.NET 页面代码隐藏中成功地执行完全相同的请求,而它在经典 ASP 页面中给出错误。 我刚刚尝试将经典 ASP 页面从 MSXML2.ServerXMLHTTP 对象转换为 WinHttp.WinHttpRequest.5.1。这同样适用于许多请求,但最终它也得到了安全通道支持错误。 现在我将站点从集成模式更改为经典模式,以使其运行起来更像 IIS 6。在过去的 24 小时内,该问题至少发生了两次。 我想这是低于 HTTP(S) 级别的网络问题。查看两台服务器上的系统、应用程序和安全事件日志。此外,如果可能,修改您的脚本以编写最简单的 txt 文件,使用“开始时间”(open
方法之前)和“停止时间”(send
方法之后)。查看服务失败时的时差。还可以尝试调用setOption
方法,值为SXH_OPTION_IGNORE_SERVER_SSL_CERT_ERROR_FLAGS
- 我不相信这会有所帮助,但请尝试。
您发送的请求是否引用了运行脚本的同一台服务器?
【参考方案1】:
从 2003 迁移到 2008 R2 后,我遇到了完全相同的问题并找到了解决方案。变化:
Set objhttp = Server.CreateObject ("MSXML2.ServerXMLHTTP.6.0")
到:
Set objhttp = Server.CreateObject ("MSXML2.XMLHTTP.6.0")
你的问题就会消失。
我试图找出这两个对象的优缺点,但还没有找到不使用 XMLHTTP 的理由。
【讨论】:
“MSXML2.XMLHTTP.6.0”不支持“waitForResponse”方法。这是一个骗局。 这种方法很危险,因为您将一个为服务器端脚本设计的组件替换为在客户端脚本中工作的组件设计。【参考方案2】:我遇到了同样的问题,并尝试了各种帖子下提供的许多解决方案,但最终都没有成功,直到现在。我将参考问题详细说明对我有用的解决方案,因为在我的情况下它是 PayPal。我没有打开新帖子,因为这可能不只是未来贝宝的问题。
该解决方案是一些 *** 发布的针对类似问题的解决方案的组合,但这似乎是最好的补充。
问题
尝试使用 PayPal 沙盒在 Windows Server 2008 上使用经典 ASP 测试 PayPal IPN 返回错误“安全通道支持中发生错误”。
为什么会出现问题
PayPal 要求与其系统的所有通信尽可能安全。您将需要一个 TLS 1.2 的连接。默认情况下,Windows Server 2008 不是 TLS 1.2。
PayPal 说您需要 Verisign G5 证书,这让您感到困惑,您需要为服务器根目录而不是运行代码的域。我也没有安装任何 PayPal 证书,因为我不使用 API。我认为您也不需要来自 HTTPS 站点的通信 - 尽管我的域使用标准 GoDaddy EV 证书进行了保护,尽管我在非 HTTPS 站点上进行了测试,并且效果也很好。
我的解决方案
首先通过SSL Labs 检查您的服务器使用哪种安全措施。 应该是 TLS1.2 或更高版本,而不是其他 TLS 或 SSL。它还必须具有 SHA256 加密。 您可能需要修补服务器:https://support.microsoft.com/en-us/kb/3106991。
使用 IISCrypto 设置正确的 TLS 和密码。我使用了 *** 上其他地方提供的注册表更改,但这不起作用,实际上完全搞砸了使用 HTTPS 帖子的所有服务器,而不仅仅是我的开发站点! IISCrypto 也处理密码。
确保您的应用程序池是 v4.5,这本身并不清楚,因为 IIS 可能只提供 v4.0 作为选项。然而,这实际上可能是 v4.5。您可以通过https://msdn.microsoft.com/en-us/library/hh925568(v=vs.110).aspx 验证这一点。
在您的代码中,您需要使用Server.CreateObject ("MSXML2.XMLHTTP.6.0")
,而不是上面提到的Server.CreateObject ("MSXML2.ServerXMLHTTP.6.0")
。
现在我不知道为什么非服务器 XMLHTTP 的工作方式似乎与它背后的文档相反。现在,经过 10 天的压力、恐慌和沮丧,我不在乎!我希望这对其他人有用。
找到解决方案是一场噩梦,所以我将在下面添加一些短语以帮助其他人搜索:
PayPal IPN 因服务器错误而失败
PayPal SSL Windows 2008 错误
安全通道支持发生错误
经典的 ASP PayPal 沙盒 SSL 错误
我要公开感谢 Rackspace 和 GoDaddy 在这方面的帮助。我想公开声明,我发现贝宝拥有有史以来最糟糕的技术支持,并且根本不在乎,如果他们有回应,就会不断地指向他们自己的文档。他们说自 2014 年 9 月以来他们一直在发送有关此问题的电子邮件,但我从未收到过。这些新要求在 PayPal 沙盒上有效,但在 2016 年 9 月上线。我只是在开发新解决方案时才发现它,因此需要沙盒 - 如果您正在运行,您不会知道问题,直到它出现然后你死在水里了。我的建议是尽快在 PayPal 沙盒上测试您的整个支付系统!!
【讨论】:
【参考方案3】:以上答案均不适用于我的情况。然后我跳到这里的链接:
https://support.microsoft.com/en-za/help/3140245/update-to-enable-tls-1-1-and-tls-1-2-as-a-default-secure-protocols-in
此更新为 Windows Server 2012、Windows 7 Service Pack 1 (SP1) 和 Windows Server 2008 R2 SP1 中的传输层安全性 (TLS) 1.1 和 TLS 1.2 提供支持。
使用 WinHTTP 为使用 WINHTTP_OPTION_SECURE_PROTOCOLS 标志的安全套接字层 (SSL) 连接编写的应用程序和服务不能使用 TLS 1.1 或 TLS 1.2 协议。这是因为此标志的定义不包括这些应用程序和服务。
此更新添加了对 DefaultSecureProtocols 注册表项的支持,允许系统管理员在使用 WINHTTP_OPTION_SECURE_PROTOCOLS 标志时指定应使用哪些 SSL 协议。
这可以允许某些使用 WinHTTP 默认标志构建的应用程序能够在本地利用较新的 TLS 1.2 或 TLS 1.1 协议,而无需对应用程序进行任何更新。
当某些 Microsoft Office 应用程序从 SharePoint 库或 Web 文件夹打开文档、用于 DirectAccess 连接的 IP-HTTPS 隧道以及使用 WebDav、WinRM 等技术的其他应用程序时,就会出现这种情况等。
此更新不会更改手动设置安全协议而不是传递默认标志的应用程序的行为。
Client service
上的Windows 2008 R2
服务器通过 TLS 出站到服务器返回了有问题的错误。我认为这可能是密码套件兼容性。 Wireshark
跟踪表明 Client Hello
请求中的版本是 TLS 1.0,但服务器需要 TLS 1.2。从客户端服务发送到出站服务器的密码套件很好。问题是 Windows 服务器上的客户端服务或应用程序默认使用系统默认值,而不是 TLS 1.2。
解决方案是添加一个名为 DefaultSecureProtocols
的注册表子项,其值对应于应支持的 TLS 版本。将上述注册表子项(类型为 DWORD
)添加到以下位置:
对于 Internet Explorer 修复,您可以将标题为 SecureProtocols
的类似注册表子项添加到以下位置,类型为 DWORD
:
您可以在下面找到两个子键的值表:
DefaultSecureProtocols Value Protocol enabled
0x00000008 Enable SSL 2.0 by default
0x00000020 Enable SSL 3.0 by default
0x00000080 Enable TLS 1.0 by default
0x00000200 Enable TLS 1.1 by default
0x00000800 Enable TLS 1.2 by default
例如:
管理员想要覆盖 WINHTTP_OPTION_SECURE_PROTOCOLS 的默认值以指定 TLS 1.1 和 TLS 1.2。
获取 TLS 1.1 (0x00000200) 的值和 TLS 1.2 (0x00000800) 的值,然后在计算器中将它们相加(在程序员模式下),生成的注册表值将是 0x00000A00。 p>
我将 0x00000A00 应用为两个子项的值,它成功解决了问题。
如果您不想手动输入注册表子项和值,还可以从 Microsoft 获得 Easy Fix(链接在此处:https://aka.ms/easyfix51044)。
【讨论】:
在 Windows 7 上,即使使用 MSXML2.ServerXMLHTTP.6.0(无需更改为 MSXML2.XMLHTTP.6.0),此 Easy Fix 也能正常工作。安装后必须重启机器。 有一个单独的问题是关于如何设置注册表设置。我建议检查一下。这是命令行上的单行代码,我可以确认它有效。 superuser.com/questions/1080317/…【参考方案4】:这一切都有效,但是在带有 IIS7.5 和经典 asp 的 Windows 7 上支持 TLS1.2 的“关键”缺失位正在注册表中设置:-
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\WinHttp]
"DefaultSecureProtocols"=dword:00000800
我希望这可以为您节省一天的时间,重新启动和挠头! :)
这段代码 sn-p 对测试很有用。 https://www.howsmyssl.com/
<%
Set winhttp = Server.CreateObject("WinHTTP.WinHTTPRequest.5.1")
winhttp.open "GET", "https://howsmyssl.com/a/check", False
winhttp.Send
Response.Write winhttp.responseText
%>
【讨论】:
【参考方案5】:在一个 Windows Server 2016 Classic ASP 脚本中,从 Windows Server 2012 R2 获取一个 HTTPS URL,我最近不得不从 SecureProtocols 中删除 SSL 2.0 以阻止这个安全通道错误 -2147012739。
' Use the latest client
Set httpClient = Server.CreateObject("WinHttp.WinHttpRequest.5.1")
' allow only TLS 1.2 or TLS 1.1
Const WHR_SecureProtocols = 9
httpClient.Option(WHR_SecureProtocols) = &h0800 + &h0200
' Other values: TLS 1.0 &h0080, SSL 3.0 &h0020, SSL 2.0 &h0008
' NB Including SSL 2.0 stops https to Windows Server 2012 R2 working
' Other options you may want to set, from https://docs.microsoft.com/en-us/windows/desktop/winhttp/winhttprequestoption
' Ignore certificate errors
Const WHR_SslErrorIgnoreFlags = 4
httpClient.Option(WHR_SslErrorIgnoreFlags) = &h3300
' Don't bother checking cert, or risking failure if we can't check
Const WHR_EnableCertificateRevocationCheck = 18
httpClient.Option(WHR_EnableCertificateRevocationCheck) = False
【讨论】:
现在启用和禁用密码套件的更简单、更强大的方法是使用定期更新的 IIS Crypto nartac.com/Products/IISCrypto【参考方案6】:故障排除错误代码:
-
-2147012739 是 HRESULT。
十六进制表示 0x80072F7D。
查看 LOWORD:0x2F7D。
将其转换回十进制:12157。
查找 12157 错误代码。
发现它匹配:ERROR_WINHTTP_SECURE_CHANNEL_ERROR
一点 Google-fu 发现 http://msdn.microsoft.com/en-us/library/windows/desktop/aa383770(v=vs.85).aspx 声明:
ERROR_WINHTTP_SECURE_CHANNEL_ERROR
12157
表示发生了与安全通道有关的错误(相当于“winerror.h”头文件中列出的以“SEC_E_”和“SEC_I_”开头的错误代码)。
但是,您已经发现了这一点,因为您收到的消息是“描述:安全通道支持中发生错误”。所以这让我们回到了开始的地方。
我的另一个观察是您的代码是一个非异步 WinHTTP 请求(我知道它必须在 ASP 中运行),但是,由于频率很高,您的机器可能会处理更多一个 WinHTTP 请求。我见过一些 Windows 故意通过阻止延迟请求来限制活动并发 WinHTTP 请求的总数。例如,在 Windows 7 机器上,一个进程不能向同一个远程服务器发出超过 2 个并发请求。即第 3、4... 个请求将被阻止,直到前两个完成。
一种解决方案是通过多个应用程序池或多个服务器对传入请求进行负载平衡。
【讨论】:
【参考方案7】:我们在这个问题上有所不同,确实花了我们一些时间来弄清楚。 情况如下: 一个较旧的 Linux 服务器托管一个用 php 编写的应用程序,并通过 Web 服务调用提供数据。服务器正在使用 HTTPS。来自各种客户端的调用是通过使用 winHTTP 5.2 库的代码进行的。 (Winhttp.dll)
症状:我们的客户现在在使用“POST”命令重复调用 winHTTP 时收到零星的错误消息。消息是“提供给函数的缓冲区太小。”或“安全通道支持中发生错误”。经过大量搜索,我们发现客户端的服务器在事件查看器中记录了与可见错误消息相对应的“Schannel 事件 ID 36887 警报代码 20”。
解决方案:我们发现我们的旧 Linux 服务器不支持 TLS 1.2。 (CentOS 5.11) 我们还了解到,我们的一些客户最近(2016 年夏季)对其 Microsoft 服务器进行了更新。 (Server 2008, server 2012) 修复是强制他们的服务器使用 TLS 1.1 进行 web 服务调用。对我来说相当奇怪的部分是 Internet Explorer 中用于更改 TLS 的设置对问题没有影响。但是,通过更改组策略中的设置,我们能够解决问题。我们在这件事上的技术顾问指出,这个变化真的很模糊,但是第三方供应商已经提供了一个快速的解决方案。该工具被称为来自 Nartac 的 IIS Crypto。 https://www.nartac.com/Products/IISCrypto/Download 该工具允许您专门选择协议。 我们现在正在获得一个新服务器来托管我们的应用程序(CentOS 6),然后应该能够使用 TLS 1.2 协议!
【讨论】:
【参考方案8】:几个月前我自己也遇到了这个错误。大多数情况下,此问题是由无效的 SSL 证书引起的。考虑到在发帖时您刚刚迁移到新服务器,您可能只需要重新安装 SSL 证书。
我意识到这个问题已经过时了,但希望其他人可以从我的回答中受益。
【讨论】:
以上是关于安全通道支持中发生错误 - 经典 ASP HTTP 请求的主要内容,如果未能解决你的问题,请参考以下文章