HttpWebrequest 失败,内部异常为:身份验证失败,因为远程方已关闭传输流。

26

使用C#、.Net 4.5,我正在尝试通过HttpWebRequest向远程服务器发送Web请求。请参见下面的代码。 我已经尝试了一些论坛上提出的解决方案,但最终都遇到了相同的错误。请参见下面的堆栈跟踪。 当调用request.GetReponse()方法时抛出错误。

额外的信息,基本上,我正在尝试调用安装在远程服务器上的vmware的vCenter组件的reloadSslCertificate函数。目前,这个错误只发生在vCenter 5.5上。在5.1及以下版本中可以正常工作。

        var uri = String.Format("https://{0}/some_url", serverName);
        var request = (HttpWebRequest)WebRequest.Create(uri);
        request.KeepAlive = true;
        request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
        request.Headers.Set(HttpRequestHeader.AcceptLanguage, "en-US,en;q=0.8");
        request.Credentials = credential;
        request.CookieContainer = cookieContainer;


        var response = request.GetResponse();
异常: System.Net.WebException:基础连接被关闭:在发送时发生意外错误。 ---> System.IO.IOException:由于远程方已关闭传输流而导致身份验证失败。在System.Net.Security.SslState.StartReadFrame(Byte[] buffer, Int32 readBytes, AsyncProtocolRequest asyncRequest)处 开始读取帧,在System.Net.Security.SslState.StartReceiveBlob(Byte[] buffer, AsyncProtocolRequest asyncRequest)处开始接收Blob,在System.Net.Security.SslState.CheckCompletionBeforeNextReceive(ProtocolToken message, AsyncProtocolRequest asyncRequest)处检查完成下一个接收之前的协议令牌消息,在System.Net.Security.SslState.StartSendBlob(Byte[] incoming, Int32 count, AsyncProtocolRequest asyncRequest)处开始发送Blob,在System.Net.Security.SslState.ForceAuthentication(Boolean receiveFirst, Byte[] buffer, AsyncProtocolRequest asyncRequest)处强制进行身份验证,在System.Net.Security.SslState.ProcessAuthentication(LazyAsyncResult lazyResult)处处理身份验证,在System.Net.TlsStream.CallProcessAuthentication(Object state)处调用ProcessAuthentication,在System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)处运行内部线程上下文,在System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)处执行线程上下文,在System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)处运行上下文,在System.Net.TlsStream.ProcessAuthentication(LazyAsyncResult result)处处理身份验证,在System.Net.TlsStream.Write(Byte[] buffer, Int32 offset, Int32 size)处写入字节,在System.Net.PooledStream.Write(Byte[] buffer, Int32 offset, Int32 size)处写入字节,在System.Net.ConnectStream.WriteHeaders(Boolean async)处写入标头。--- 内部异常堆栈跟踪结束 --- 在System.Net.HttpWebRequest.GetResponse()处抛出此异常。谢谢!
3个回答

27

我只是想分享一下,这个问题已经得到解决。

我刚刚修改了代码的一部分,在发出Web请求之前设置安全协议。

来自:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

收件人:

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

事实证明,vCenter 5.5在其配置中使用TLS作为其SSL协议。当人们遇到同样的问题时,希望这篇文章能够有所帮助。


1
点赞,因为这对我非常有帮助,但是对于其他人来说:还要检查并查看是否有新版本可以在此处附加。对于我的需求,我需要Tls12而不是Tls。 - Jess K.
如果我在尝试使用CMD生成代码时遇到此错误,您有什么建议? - Zeeshan Adil

18

我们遇到了同样的异常情况。在我们的情况下,答案与 @Dennis Laping 的答案非常相似。另一个团队已经在 Rancher 负载均衡器中设置了我们正试图访问的服务,这个负载均衡器默认不允许 TLS 1.0 或 SSL3。恰好在 .NET 中,当前默认的 SecurityProtocol (未设置)只允许使用 TLS 1.0 或 SSL3。

当我们将 SecurityProtocol 设置如下,一切都正常工作:

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

尽管如此,有关SecurityProtocol的文档指出:

您的代码不应该隐式地依赖于使用特定的保护级别,或者假设默认情况下使用给定的安全级别。如果您的应用程序依赖于使用特定的安全级别,则必须明确指定该级别,并检查确保它实际上正在已建立的连接上使用。此外,您的代码应该在面对支持的协议发生变化时具有健壮性,因为此类变化通常会在很短时间内进行,以缓解新兴威胁。

我们将重新评估协议情况的最佳解决方案,但现在我希望这可以帮助其他人。


2
+1 为你的救命之恩点赞。为了让我们的服务在ssllabs上获得A级评分,我们严格限制了终端节点所允许的协议 - 这导致了客户端应用程序出现问题。你的答案成功解决了这个问题!感谢你! - Toastor
如果我在尝试使用CMD生成代码时遇到此错误,您有什么建议? - Zeeshan Adil

1

看这个链接,它对我有用:
如何使用TcpClient执行与HttpWebRequest类似的HTTPS操作?

Dim trust_all_certificates As New CertificateOverride
ServicePointManager.ServerCertificateValidationCallback = AddressOf trust_all_certificates.RemoteCertificateValidationCallback
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3

Public Class CertificateOverride

    Public Function RemoteCertificateValidationCallback(ByVal sender As Object, ByVal certificate As X509Certificate, ByVal chain As X509Chain, ByVal sslPolicyErrors As SslPolicyErrors) As Boolean

        'CertEXPIRED = 2148204801
        'CertVALIDITYPERIODNESTING = 2148204802
        'CertPATHLENCONST = 2148204804
        'CertROLE = 2148204803
        'CertCRITICAL = 2148204805
        'CertPURPOSE = 2148204806
        'CertISSUERCHAINING = 2148204807
        'CertMALFORMED = 2148204808
        'CertUNTRUSTEDROOT = 2148204809
        'CertCHAINING = 2148204810
        'CertREVOKED = 2148204812
        'CertUNTRUSTEDTESTROOT = 2148204813
        'CertREVOCATION_FAILURE = 2148204814
        'CertCN_NO_MATCH = 2148204815
        'CertWRONG_USAGE = 2148204816
        'CertUNTRUSTEDCA = 2148204818

        Return True

    End Function

End Class

附言

我之前插入了这行代码,以确保来自服务器端的证书被接受:ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3


谢谢。我会尝试的。 - Dennis Laping
如果我在使用CMD生成代码时遇到错误,有什么意见吗? - Zeeshan Adil
Zeeshan,你能给我们更多的信息吗?我认为你应该打开一个新的问题(如果不存在),因为我认为你遇到了另一种类型的“错误”。 - GenTech

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