“基础连接已关闭:发送中发生意外错误。” 带有SSL证书


119

问题:我在日志中收到此异常“基本连接已关闭:发送中发生意外错误”,这随机中断了[1小时-4小时]期间我们与电子邮件营销系统的OEM集成。

我的网站托管在带有IIS 7.5.7600的Windows Server 2008 R2上。该网站具有大量的OEM组件和全面的仪表板。一切与网站的所有其他元素都可以正常工作,但电子邮件营销组件之一除外,我们将其用作仪表板中的iframe解决方案。它的工作方式是,我发送带有所有凭据的httpWebRequestobject,并得到一个返回的网址,该网址已放入iframe中,并且可以正常工作。但是它只能工作一段时间[1小时-4小时],然后我得到以下异常“基本连接已关闭:发送时发生意外错误”,即使系统尝试从httpWebRequest获取URL,也是如此由于相同的异常而失败。使它再次起作用的唯一方法是回收应用程序池,或者在web.config中编辑任何内容。

选项尝试

明确添加, keep-alive = false

keep-alive = true

增加了超时时间: <httpRuntime maxRequestLength="2097151" executionTimeout="9999999" enable="true" requestValidationMode="2.0" />

我已将此页面上载到非SSL网站,以检查生产服务器上的SSL证书是否正在建立连接以删除某些操作。

朝着分辨率的任何方向都将受到赞赏。

代码:

Public Function CreateHttpRequestJson(ByVal url) As String
    Try
        Dim result As String = String.Empty
        Dim httpWebRequest = DirectCast(WebRequest.Create("https://api.xxxxxxxxxxx.com/api/v3/externalsession.json"), HttpWebRequest)
        httpWebRequest.ContentType = "text/json"
        httpWebRequest.Method = "PUT"
        httpWebRequest.ContentType = "application/x-www-form-urlencoded"
        httpWebRequest.KeepAlive = False
        'ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3

        'TODO change the integratorID to the serviceproviders account Id, useremail 
        Using streamWriter = New StreamWriter(httpWebRequest.GetRequestStream())
            Dim json As String = New JavaScriptSerializer().Serialize(New With { _
            Key .Email = useremail, _
            Key .Chrome = "None", _
            Key .Url = url, _
            Key .IntegratorID = userIntegratorID, _
            Key .ClientID = clientIdGlobal _
            })

            'TODO move it to the web.config, Following API Key is holonis accounts API Key
            SetBasicAuthHeader(httpWebRequest, holonisApiKey, "")
            streamWriter.Write(json)
            streamWriter.Flush()
            streamWriter.Close()

            Dim httpResponse = DirectCast(httpWebRequest.GetResponse(), HttpWebResponse)
            Using streamReader = New StreamReader(httpResponse.GetResponseStream())
                result = streamReader.ReadToEnd()
                result = result.Split(New [Char]() {":"})(2)
                result = "https:" & result.Substring(0, result.Length - 2)
            End Using
        End Using
        Me.midFrame.Attributes("src") = result
    Catch ex As Exception
        objLog.WriteLog("Error:" & ex.Message)
        If (ex.Message.ToString().Contains("Invalid Email")) Then
            'TODO Show message on UI
        ElseIf (ex.Message.ToString().Contains("Email Taken")) Then
            'TODO Show message on UI
        ElseIf (ex.Message.ToString().Contains("Invalid Access Level")) Then
            'TODO Show message on UI
        ElseIf (ex.Message.ToString().Contains("Unsafe Password")) Then
            'TODO Show message on UI
        ElseIf (ex.Message.ToString().Contains("Invalid Password")) Then
            'TODO Show message on UI
        ElseIf (ex.Message.ToString().Contains("Empty Person Name")) Then
            'TODO Show message on UI
        End If
    End Try
End Function


Public Sub SetBasicAuthHeader(ByVal request As WebRequest, ByVal userName As [String], ByVal userPassword As [String])
    Dim authInfo As String = Convert.ToString(userName) & ":" & Convert.ToString(userPassword)
    authInfo = Convert.ToBase64String(Encoding.[Default].GetBytes(authInfo))
    request.Headers("Authorization") = "Basic " & authInfo
End Sub`

你有没有解决这个问题?
Brett G

11
是的,我能够使用此代码ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls或SecurityProtocolType.Ssl3
Arvind Morwal 2014年

我正因同样的问题而死。花了我几个小时努力解决同一问题。感谢您的评论,它挽救了我的生命。
Sameers Javed 2015年

2
@ user3458212,您应该在评论中添加您的评论
icc97

2
就我而言,在Visual Studio 15中运行网站一切正常,但是最后,由于我无法升级服务器中的框架,并且强制TLS 1.2和禁用keep-alive不起作用,因此我必须设置一个中间Web服务器以代理断开连接的目标Web服务器。
何塞·罗伯托·加西亚·奇科

Answers:


193

对我来说是tls12:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

42
请注意,您必须小心,因为此更改是AppDomain的全局更改,并且将导致对不提供TLS 1.2的任何站点的调用失败(如果要传输的数据确实是敏感的,您可能更希望这样做)。要使用TLS 1.2但仍允许使用1.1和1.0,则必须对其进行OR运算:ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
Dusty

同样在这里,您救了我的命,花了很多时间弄清楚RestSharp出了什么问题
darul75 '17

此解决方案还适用于不使用RestSharp的用户以及不使用ServicePointManager的用户。只需将上面的行复制并粘贴到您的WebRequest调用或用于发出请求的内容之前。由于上述原因,我最初忽略了此解决方案。
goku_da_master

或只是将其添加到已经存在的位置... System.Net.ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
uosjead '18

8
为此,请在PowerShell中将它们“二进制或”在一起,如下所示:[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls
Adam S

62

如果您坚持使用.Net 4.0,并且目标站点正在使用TLS 1.2,则需要以下行。 ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;

来源:TLS 1.2和.NET支持:如何避免连接错误


5
太棒了!我只是添加(SecurityProtocolType)768可以用于“ Tls11”(即TLS 1.1)的代码。
所罗门·鲁兹基

2
这确实有帮助。它挽救了我的一天。我必须坚持使用.Net 2.0。
郝阮

22

下面的代码解决了这个问题

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls Or SecurityProtocolType.Ssl3

5
但是,请记住,这ServicePointManager.SecurityProtocol是一个静态对象,这意味着更改此值将影响所有子序列WebRequestWebClient调用。AppDomain如果要ServicePointManager进行其他设置,可以单独创建。有关更多详细信息,请参见stackoverflow.com/questions/3791629/…
2015年

1
有用的额外阅读了解一下这个代码是这样做的:stackoverflow.com/questions/26389899/...
乔恩·施耐德

@Marnee我将其放在应用程序的组合根目录中,因此将其设置在发生任何I / O之前
SD的JG,

@Marnee将其放在静态构造函数中,因此在第一次访问该类时,它只执行一次。我必须启用所有协议才能覆盖所有情况。
Nyerguds

14

几天来我一直在遇到一个同样的问题,它的集成也只是“以前可以使用”。

出于纯粹的沮丧,我只是尝试

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

这为我解决了..即使集成严格只使用SSLv3。

我意识到,自Fiddler报告说存在“空的TLS协商密码”之类的东西以来,这种情况就不存在了。

希望它能工作!


请注意,即使您的代码不需要TLS,但如果服务器正在与DOES通信,它也会尝试与TLS协商,如果不需要,则失败。空的TLS协商密码是期望您最终提供的TLS协议交换的插槽。它可能“以前可以使用”,因为服务器管理员可能刚刚在与您的应用程序进行通信的服务器上启用了TLS。
vapcguy

13

就我而言,我要连接的站点已升级到TLS 1.2。结果,为了支持它,我必须在Web服务器上安装.net 4.5.2。


可以在计算机上的注册表级别完成此操作吗?我已经禁用了所有SSL协议,并保留了TLS 1.0、1.1、1.2,但是据我了解,除TLS 1.2之外的任何内容都应尽快删除,以便与PCI兼容。
brendo234 '18

12

转到您的web.config / App.config以验证您正在使用哪个.net运行时

  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
  </startup>

解决方法如下:

  1. .NET 4.6及更高版本。您无需执行任何其他工作即可支持TLS 1.2,默认情况下支持该功能。

  2. .NET 4.5。支持TLS 1.2,但它不是默认协议。您需要选择使用它。以下代码将TLS 1.2设置为默认值,请确保在连接到安全资源之前执行它:

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12

  1. .NET 4.0。不支持TLS 1.2,但是如果系统上安装了.NET 4.5(或更高版本),那么即使您的应用程序框架不支持TLS 1.2,您仍然可以选择使用TLS 1.2。唯一的问题是.NET 4.0中的SecurityProtocolType没有TLS1.2的条目,因此我们必须使用此枚举值的数字表示形式:

ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;

  1. .NET 3.5或更低版本。不支持TLS 1.2(*),并且没有解决方法。将您的应用程序升级到该框架的最新版本。

6

我发现这表明您正在部署代码的服务器上安装了旧的.NET框架,该框架不支持TLS 1.1或TLS 1.2。解决步骤:

  1. 在生产服务器上安装最新的.NET Runtime(IIS和SQL)
  2. 在开发计算机上安装最新的.NET Developer Pack
  3. 将您的Visual Studio项目中的“目标框架”设置更改为最新的.NET框架。

您可以从以下URL获得最新的.NET Developer Pack和Runtime:http : //getdotnet.azurewebsites.net/target-dotnet-platforms.html


将目标框架从4.5.2更改为4.6.1,并开始工作,谢谢Patrick。
Vivek Sharma

4

我们遇到了一个问题,正在访问我们的API的网站正在获取“基础连接已关闭:发送中发生意外错误。” 信息。

他们的代码混合了.NET 3.x和2.2,据我了解,这意味着他们正在使用TLS 1.0。

下面的答案可以通过启用TLS 1.0,SSL 2和SSL3来帮助您诊断问题,但非常清楚,您不想长期这样做,因为这三个协议都被视为不安全,因此不再用过的

为了使IIS能够响应其API调用,我们必须在IIS的服务器上添加注册表设置以显式启用TLS版本-注意:在进行以下更改后,您必须重新启动Windows服务器(不仅仅是IIS服务):

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
1.0\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
1.0\Server] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
1.1\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
1.1\Server] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
1.2\Client] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\TLS
1.2\Server] "DisabledByDefault"=dword:00000000 "Enabled"=dword:00000001

如果这样做没有效果,您也可以尝试添加SSL 2.0条目:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Client]
"DisabledByDefault"=dword:00000000
"Enabled"=dword:00000001

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Server]
"DisabledByDefault"=dword:00000000
"Enabled"=dword:00000001

需要明确的是,这不是一个很好的解决方案,正确的解决方案是让调用方使用TLS 1.2,但是以上内容可以帮助诊断这是问题所在。

您可以使用以下powershell脚本加快添加这些reg条目的速度:

$ProtocolList       = @("SSL 2.0","SSL 3.0","TLS 1.0", "TLS 1.1", "TLS 1.2")
$ProtocolSubKeyList = @("Client", "Server")
$DisabledByDefault = "DisabledByDefault"
$Enabled = "Enabled"
$registryPath = "HKLM:\\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\"

foreach($Protocol in $ProtocolList)
{
    Write-Host " In 1st For loop"
        foreach($key in $ProtocolSubKeyList)
        {         
            $currentRegPath = $registryPath + $Protocol + "\" + $key
            Write-Host " Current Registry Path $currentRegPath"
            if(!(Test-Path $currentRegPath))
            {
                Write-Host "creating the registry"
                    New-Item -Path $currentRegPath -Force | out-Null             
            }
            Write-Host "Adding protocol"
                New-ItemProperty -Path $currentRegPath -Name $DisabledByDefault -Value "0" -PropertyType DWORD -Force | Out-Null
                New-ItemProperty -Path $currentRegPath -Name $Enabled -Value "1" -PropertyType DWORD -Force | Out-Null    
    }
}
 
Exit 0

这是Microsoft帮助页面中“ 为VMM设置TLS ”脚本的修改版本。此basics.net文章最初是使我有了这些设置的想法的页面。


我们的问题是围绕Team City的发布管道,当我们为您的实时服务器更改证书时突然停止。我们已经将服务器更改为仅使用TLS1.2,并且我们的Team City管道停止了工作……像梦一样工作……添加了reg条目并重新启动了服务器……BOOM!谢谢tomRedox!
Gwasshoppa

@Gwasshoppa,只是重申以上内容只是诊断问题的权宜之计。现在您知道这是TLS版本的问题,解决方案是更改发布管道,使其可以与TLS1.2一起使用,然后再次关闭TLS <1.2和SSL 2和3。我也略微更新了上面的答案,以强调这一点。
tomRedox


2

如果可以帮助某人,我们的证书丢失是一个问题。环境是带有.Net 4.6的Windows Server 2016 Standard。

有一个自托管的WCF服务https URI,对其执行Service.Open()不会出错。另一个线程将继续访问https:// OurIp:443 / OurService?wsdl以确保该服务可用。访问失败的WSDL的原因是:

基础连接已关闭:发送时发生意外错误。

无法将ServicePointManager.SecurityProtocol与适用的设置一起使用。使用服务器角色和功能也无济于事。然后介入SE的Jaise George,在几分钟内解决了问题。Jaise在IIS中安装了一个自签名证书,以此来解决问题。这是他为解决此问题所做的事情:

(1)打开IIS管理器(inetmgr)(2)单击左侧面板中的服务器节点,然后双击“服务器证书”。(3)单击右侧面板上的“创建自签名证书”,然后键入任何您想要的友好名称。(4)单击左侧面板中的“默认网站”,单击右侧面板中的“绑定”,单击“添加”,选择“ https”,选择刚创建的证书,然后单击“确定”。(5)访问https URL,应该可以访问。


您可能以为服务器管理员会添加SSL证书!天哪!大声笑:)我可以看到这种情况的发生-或者需要更新的过期证书可能是更适用的方案。
vapcguy

2

您只需将应用程序版本从4.0更改为4.6,然后发布这些代码。

还添加以下代码行:

httpRequest.ProtocolVersion = HttpVersion.Version10; 
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

1

使用HTTP调试代理可能会导致这种情况-例如Fiddler。

我正在从本地文件(对Apple.com进行身份验证)加载PFX证书,但由于Fiddler无法继续传递此证书而失败。

尝试禁用Fiddler进行检查,如果这是解决方案,则您可能需要在计算机上安装证书,或者以某种方式使Fiddler可以使用它。


0

下面的代码解决了我的问题:

request.ProtocolVersion = HttpVersion.Version10; // THIS DOES THE TRICK
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.