C#HttpWebRequest SEC_I_RENEGOTIATE间歇性错误

我正在使用C#(。Net framework 3.5)应用程序中的SSL POST调用来处理登录/注销function。 通过HttpWebRequest :: BeginGetResponse()从服务器获取响应的工作时间为80%,但另外20%是间歇性抛出:

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

我使用另一个问题中的建议文章启用了SSL跟踪。 这在请求跟踪中产生了两种不同的模式。

似乎在执行期间,错误:

 System.Net Error: 0 : [3680] Decrypt returned SEC_I_RENEGOTIATE. 

正在接收,导致重新启动安全上下文。 当发生这种情况并且成功时,这是输出(注意我省略了实际地址):

 System.Net Error: 0 : [3680] Decrypt returned SEC_I_RENEGOTIATE. System.Net Information: 0 : [3680] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 4bec0d0:4c0a8a8, targetName = [omitted].com, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation) System.Net Information: 0 : [3680] InitializeSecurityContext(In-Buffer length=0, Out-Buffer length=78, returned code=ContinueNeeded). System.Net Information: 0 : [7148] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 4bec0d0:4c0a8a8, targetName = [omitted].com, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation) System.Net Information: 0 : [7148] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=ContinueNeeded). System.Net Information: 0 : [7148] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 4bec0d0:4c0a8a8, targetName = [omitted].com, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation) System.Net Information: 0 : [7148] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=ContinueNeeded). System.Net Information: 0 : [7148] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 4bec0d0:4c0a8a8, targetName = [omitted].com, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation) System.Net Information: 0 : [7148] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=1259, returned code=ContinueNeeded). System.Net Information: 0 : [7148] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 4bec0d0:4c0a8a8, targetName = [omitted].com, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation) System.Net Information: 0 : [7148] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=ContinueNeeded). System.Net Information: 0 : [7148] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 4bec0d0:4c0a8a8, targetName = [omitted].com, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation) System.Net Information: 0 : [7148] InitializeSecurityContext(In-Buffers count=2, Out-Buffer length=0, returned code=OK). System.Net Information: 0 : [7148] Remote certificate: [Version] V1 

失败时:

 System.Net Error: 0 : [3680] Decrypt returned SEC_I_RENEGOTIATE. System.Net Information: 0 : [3680] InitializeSecurityContext(credential = System.Net.SafeFreeCredential_SECURITY, context = 4bec0d0:4c0ab50, targetName = [omitted].com, inFlags = ReplayDetect, SequenceDetect, Confidentiality, AllocateMemory, InitManualCredValidation) System.Net Information: 0 : [3680] InitializeSecurityContext(In-Buffer length=0, Out-Buffer length=78, returned code=ContinueNeeded). System.Net Error: 0 : [3680] Exception in the HttpWebRequest#20730349:: - The request was aborted: Could not create SSL/TLS secure channel. System.Net Verbose: 0 : [3680] HttpWebRequest#20730349::EndGetResponse() System.Net Error: 0 : [3680] Exception in the HttpWebRequest#20730349::EndGetResponse - The request was aborted: Could not create SSL/TLS secure channel. 

我当然能抓住这个例外,但正确处理的是什么?

我的应用程序是否有办法防止(或正确处理)这些错误? 当它发生时,它似乎经常出现错误一段时间,但是在一些未确定的请求数量之后再次开始工作。

谢谢!

(原始答案见下文。)

此错误通常意味着您的客户端和服务器未设置为使用相同类型的加密。 通常,解决此问题的最简单方法是明确设置要在客户端中使用的版本。

如果您使用的是.NET 4.5或更高版本,则可以尝试以下选项,从最安全到最不安全的顺序:

  • ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
  • ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11;
  • ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

如果您使用的是.NET 4.0或更早版本,则只能使用上面的最后一行,因为这些版本不支持TLSv1.1和TLSv1.2。 强烈建议您升级到.NET 4.5以利用TLSv1.2支持。

除了设置SecurityProtocol属性外,您还可能需要设置: ServicePointManager.Expect100Continue = true;

如果这些设置都不起作用,则可能意味着您的服务器仅支持SSLv3(或者更糟糕的是,SSLv2)。 如果是这种情况,请升级您的服务器! SSLv3已损坏,不应再使用。


SSLv3不再被认为是安全的。 请勿使用这些设置! 虽然这是2011年的正确答案,但它仍然只是出于历史原因。

您需要在请求之前添加以下代码行:

 ServicePointManager.Expect100Continue = true; ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3; 

从我所看到的,旧版本(.NET 2和/或Windows xp / 2003及更早版本)使用这些作为默认选项,但较新版本(.NET 3和/或Windows Vista / 2008及更新版本)不使用。

这不是一个解释,也不是一个真正的解决方案:它只是处理我们在我们的案例中找到的这个问题的最实用的方法(使用基于Apache和Java的服务器的客户端SSL证书通过HTTPS执行WCF SOAP请求)。

捕获SecurityNegotiationException并在现场重试(即,如果使用msmq,则不是重新处理消息),并在这种情况下禁止报告exception。 只需要一个性能计数器或类似的东西,这样你就可以跟踪问题是否变得更糟。

在一天结束时,这只是您的代码需要处理的与网络相关的固有问题之一。

我以为我会分享我的经验,因为我最近一直在阅读大部分的stackoverflow问题:

我见过的另一种方法是考虑HTTP Keep-Alive。 对于最新版本的.Net,它使用HTTP 1.1作为默认值,这意味着Keep-Alive设置为true,Expect100也设置为。

根据我的经验,这会在下游资源上产生粘性,并且在负载均衡器后面不可靠。

两个选择

1)恢复并再次尝试,看起来有点臭。 然而,正如Khanfx所提到的,网络问题可能会发生:网络的谬误。 TOPAZ是解决这个问题的一种方法: https ://msdn.microsoft.com/en-us/library/hh680901%28v=pandp.50%29.aspx?f=255&MSPPError =-2147217396

2)如果使用HttpClient,请通过HttpwebRequest关闭Keep-Alive或发出连接关闭标头。

HTH。