如何指定用于 WebClient 类的 SSL 协议

Posted

技术标签:

【中文标题】如何指定用于 WebClient 类的 SSL 协议【英文标题】:How to specify SSL protocol to use for WebClient class 【发布时间】:2015-08-10 02:02:39 【问题描述】:

我有一个使用 HTTPS POST 将数据发送到服务器的应用程序。我使用 System.Net.WebClient 对象来执行此操作。这是一个发送一些数据的函数:

    private byte[] PostNameValuePairs(string uri, NameValueCollection pairs)
    
        byte[] response;
        String responsestring = "";
        using (WebClient client = new WebClient())
        
            client.Headers = GetAuthenticationHeader();

            string DataSent = GetNameValueCollectionValuesString(pairs);

            try
            
                response = client.UploadValues(uri, pairs);
                responsestring = Encoding.ASCII.GetString(response);
            
            catch (Exception e)
            
                responsestring = "CONNECTION ERROR: " + e.Message;
                return Encoding.ASCII.GetBytes(responsestring);
            
            finally
            
                _communicationLogger.LogCommunication(uri, client.Headers.ToString(), DataSent, responsestring);
            
        

        return response;
    

我们传入一个以 https:// 开头的 URI

这已经很长时间了。今天,我们开始收到以下连接错误:“底层连接已关闭:发送时发生意外错误”。我们与服务器所有者进行了一些故障排除,他们最终将其范围缩小到以下几点。他们对服务器进行了更改以阻止 TLS 1.0,并说我们现在需要使用 TLS 1.1 或 1.2 发送数据。

我需要在我的 WebClient 对象(或我的函数的其他地方)中设置什么以使其使用 TLS 1.1 或 1.2 而不是 TLS 1.0?

如果有什么不同,我们将使用 .NET Framework 4.5。

【问题讨论】:

@CodeCaster,虽然答案可能与this question 相同,但不清楚它是否重复。在其他问答中根本没有提到WebClient,因此解释这些类是如何相关的可能很有用,提问者和其他读者也可能对基于每个实例设置它的潜在解决方案感兴趣,例如. 根据您使用的平台,您可能对this other question too 感兴趣。 @Bruno 当然,但这之前也已经回答过了。不过我找不到合适的,the dupe I selected 很好地解释了这一切。这个重新打开的问题现在很容易出现 "use System.Net.ServicePointManager.SecurityProtocol" 答案而没有任何适当的解释,因为已经有数百个。而且根据Set the SecurityProtocol (Ssl3 or TLS) on the .net HttpWebRequest per request,您不能按请求设置它。无论如何,WebClient 在内部使用 HttpWebRequest。 无法为每个请求设置 SecurityProtocol 绝对是一个可能的问题,特别是如果您连接到不同的服务器 - 这里有一个讨论,以及一些解释我们如何解决它的代码:***.com/questions/26160118/… 【参考方案1】:

我发现了一个在 c# 中打开和关闭 TLS 版本的稍微严格的版本。

这可以与 .Net 4.5 及更高版本一起使用。

// Remove insecure protocols (SSL3, TLS 1.0, TLS 1.1)
ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Ssl3;
ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Tls;
ServicePointManager.SecurityProtocol &= ~SecurityProtocolType.Tls11;
// Add TLS 1.2
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;

这确保即使服务器能够使用 1.0 或 1.1,我们也可以明确排除这种情况发生。

【讨论】:

【参考方案2】:

根据建议的其他问题,我可以通过在我的代码中添加以下行来解决它:

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

这从客户端禁用了 TLS 1.0,然后服务器接受了连接。

希望这可以帮助遇到同样问题的其他人。虽然答案与其他问题相似,但从提出的问题中看不出是这种情况,所以我不觉得这是重复的。

【讨论】:

您共享的代码适用于 .NET 4.0 或更高版本的应用程序。对于较旧的 .NET 应用程序,请参阅 ***.com/a/44893192/160830 如果您OR TLS11 和 TLS12 枚举值,这是否意味着您允许两者而不是禁用前者? @deroby 是的,它将同时允许 TLS11 和 TLS12。关键是禁用 TLS10。 为一个 WebClient 实例设置这个怎么样?我已经设置了多年的东西,不知道如果我在全球范围内设置它们是否会破坏。 @Simon_Weaver 如果您使用|= 而不是\,它将添加您指定的协议,同时保留旧协议。例如:ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;。另见Gwasshoppa's answer

以上是关于如何指定用于 WebClient 类的 SSL 协议的主要内容,如果未能解决你的问题,请参考以下文章

使用 ssl 的 Spring 5 WebClient

使用 Apache HttpComponents 使用 Webflux Webclient 配置 SSL

如何在 Spring 响应式 WebClient 中返回 Kotlin Coroutines Flow

无法从Dropbox下载文件,因为无法通过C#中的WebClient与SSL / TLS通道连接

在Mac上搭建带ssl协议和域名指向的Apache服务器

SSL,SSL证书,SSL协议,三个其实都是一个吗?还是说有区别呢