身份验证失败,因为远程一方已关闭传输流。

96

我正在开发一个TCP客户端,使用证书认证连接OpenSSL服务器。我使用服务器团队共享的.crt和.key文件,这些证书是通过OpenSSL命令生成的。

我正在使用SslStream对象调用SslStream.AuthenticateAsClient方法对Tcp客户端进行身份验证,其中传递了服务器IP地址、SslProtocols.Ssl3以及X509CertificateCollection

我遇到了以下错误:

身份验证失败,因为远程方已关闭传输流


2
这似乎是在后POODLE时代的一个问题:SslProtocols.Ssl3。也许你应该尝试使用SslProtocols.Tls。在 .Net 4.5 及以上版本中,你还可以使用 Tls11Tls12。请参阅SslProtocols枚举。你可能还有其他问题。 - jww
谢谢。我的问题已经解决,我附加了证书的物理路径和密码,而不是从Windows证书存储中搜索证书主题名称。 - Odelu
现在我能够从所有的SslProtocols(SSL3,Tls1和Tls2)中获取结果了。感谢您的回复。 - Odelu
@Odelu,你是如何解决这个问题的?在客户端还是服务器端? - user1108948
10个回答

181

我建议不要将SecurityProtocol限制为TLS 1.1。

推荐的解决方案是使用

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

另一种选择是添加以下注册表键:

Key: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v4.0.30319 
Value: SchUseStrongCrypto 

值得注意的是,.NET 4.6默认使用正确的协议,无需任何解决方案。


8
哇,你刚刚解决了我的问题——我尝试了各种方法——最后在这里看到了框架的提示。我把它从4.5切换到4.6.1(希望问题是框架可能使用了错误的安全协议),然后万事大吉,我的连接不再被拒绝,我也能获取到我的数据了! - Veverke
8
需要在创建请求前执行 System.Net.ServicePointManager.SecurityProtocol = ... 这条语句。重要的是要注意,在此之前必须先执行该语句。 - Tonatio
3
那个目标框架版本升级到4.6.1让我受益匪浅 :-) - Awais
我的框架设置为4.6.2。也许我需要使用TLS解决方案。 - Luminous
我正在使用4.7.2框架,同时发送请求的网站也在使用TLS 1.2,但是在10个请求中有6个会出现错误。你有什么想法吗? - Davit Mikuchadze
显示剩余2条评论

19
如果你想使用旧版的.net,请创建自己的标志并将其强制转换。
    //
    // Summary:
    //     Specifies the security protocols that are supported by the Schannel security
    //     package.
    [Flags]
    private enum MySecurityProtocolType
    {
        //
        // Summary:
        //     Specifies the Secure Socket Layer (SSL) 3.0 security protocol.
        Ssl3 = 48,
        //
        // Summary:
        //     Specifies the Transport Layer Security (TLS) 1.0 security protocol.
        Tls = 192,
        //
        // Summary:
        //     Specifies the Transport Layer Security (TLS) 1.1 security protocol.
        Tls11 = 768,
        //
        // Summary:
        //     Specifies the Transport Layer Security (TLS) 1.2 security protocol.
        Tls12 = 3072
    }
    public Session()
    {
        System.Net.ServicePointManager.SecurityProtocol = (SecurityProtocolType)(MySecurityProtocolType.Tls12 | MySecurityProtocolType.Tls11 | MySecurityProtocolType.Tls);
    }

4
您不必使用自己的类,可以直接将整数强制转换为SecurityProtocolType类型,如下所示:ServicePointManager.SecurityProtocol = (SecurityProtocolType) 48 | (SecurityProtocolType) 192 | (SecurityProtocolType) 768 | (SecurityProtocolType) 3072;这样做可以设置安全协议类型。 - Yan F.
@YanF。作者提到了“如果您使用旧版本的.Net...”,所以这很有帮助。比如 .Net 4.0。 - Gray Programmerz

12

加入下面的代码帮助我解决了这个问题。

ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls11;

11
using (var client = new HttpClient(handler))
            {
                ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
                var response = await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, apiEndPoint)).ConfigureAwait(false);
                await response.Content.ReadAsStringAsync().ConfigureAwait(false);
            }

这对我有用


1
关键的部分是以下代码行: ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;这个答案很好,因为它展示了这行代码在典型用例中应该放置的位置。 - Nick Painter
如果在那些括号之外的话,它就不能正常工作了吗? - pete

5

我在使用 ChargifyNET.dll 与 Chargify API 进行通信时遇到了相同的错误消息。将 chargify.ProtocolType = SecurityProtocolType.Tls12; 添加到配置中解决了我的问题。

以下是完整的代码片段:

public ChargifyConnect GetChargifyConnect()
{
    var chargify = new ChargifyConnect();
    chargify.apiKey = ConfigurationManager.AppSettings["Chargify.apiKey"];
    chargify.Password = ConfigurationManager.AppSettings["Chargify.apiPassword"];
    chargify.URL = ConfigurationManager.AppSettings["Chargify.url"];

    // Without this an error will be thrown.
    chargify.ProtocolType = SecurityProtocolType.Tls12;

    return chargify;
}

3

对于VB.NET,您可以在Web请求之前放置以下内容:

Const _Tls12 As SslProtocols = DirectCast(&HC00, SslProtocols)
Const Tls12 As SecurityProtocolType = DirectCast(_Tls12, SecurityProtocolType)
ServicePointManager.SecurityProtocol = Tls12

这解决了我在.NET 3.5上的安全问题。


1
当一个Web请求的终端被切换到只接受TLS1.2请求的另一台服务器时,我遇到了这个问题。尝试了许多在Stackoverflow上找到的解决方案,例如:
  1. 注册表键,
  2. 在Global.ASX OnStart中添加:
    System.Net.ServicePointManager.SecurityProtocol |= System.Net.SecurityProtocolType.Tls12; ,
  3. 在Web.config中添加。
  4. 将.NET框架更新到4.7.2 仍然收到相同的异常。
收到的异常并没有真正反映我所面临的实际问题,并且没有从服务提供商那里得到任何帮助。
为了解决这个问题,我必须添加一个新的加密套件TLS_DHE_RSA_WITH_AES_256_GCM_SHA384。我使用了IIS Crypto 2.0工具( 在此处)如下所示。

enter image description here


0
在.NET Framework 4.8中,我在发送请求之前添加了以下代码。
System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls13 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

0

我在VS 2019中遇到了以下问题:

  • 登录无法正常工作
  • 扩展 -> 管理扩展 -> 扩展信息无法检索。

我按照FunMatters的说明添加了一个新的Cipher Suite TLS_DHE_RSA_WITH_AES_256_GCM_SHA384。这也解决了我的问题。


你的回答可以通过添加更多支持信息来改进。请编辑以添加更多细节,例如引用或文档,以便他人可以确认您的答案是否正确。您可以在帮助中心中找到有关如何编写良好答案的更多信息。 - Community

0
我曾遇到这个问题并解决了它,但在发帖时(例如TSL解决方案)找到的所有解决方案都没有对我起作用,我尝试了各种方法。
我花了几个小时尝试、搜索、尝试,一切似乎都集中在TSL问题上,但这些都没能解决我的问题。
我必须使用Visual Studio Installer 并对我的VS安装进行修复。之后,问题立即得到了解决。

问题可能出在你关注文章或解决方案的方式上,就像 TSL 一样 :) - Shan

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