C#HttpWebRequest SEC_I_RENEGOTIATE间歇性错误

时间:2011-06-03 21:12:20

标签: c# ssl error-handling httpwebrequest

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

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

我使用其他问题的suggested文章启用了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.

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

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

谢谢!

3 个答案:

答案 0 :(得分:9)

(原始答案见下文。)

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

如果您使用的是.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和更新)不要。

答案 1 :(得分:4)

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

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

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

答案 2 :(得分:1)

我想我会分享我的经验,因为我最近一直在阅读大部分的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。