C#HttpWebRequest SEC_I_RENEGOTIATE间歇性错误

Str*_*yck 23 c# error-handling ssl httpwebrequest

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

The request was aborted: Could not create SSL/TLS secure channel.
Run Code Online (Sandbox Code Playgroud)

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

似乎在执行期间,错误:

System.Net Error: 0 : [3680] Decrypt returned SEC_I_RENEGOTIATE.
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

失败时:

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.
Run Code Online (Sandbox Code Playgroud)

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

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

谢谢!

Mos*_*atz 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;
Run Code Online (Sandbox Code Playgroud)

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

  • 在我的应用程序中,默认设置了这两个选项.它没有任何影响. (3认同)