【问题标题】:Specifying SSL/TLS for System.Net.HttpWebRequest through App.config通过 App.config 为 System.Net.HttpWebRequest 指定 SSL/TLS
【发布时间】:2017-08-03 18:31:56
【问题描述】:

我需要将 JSON 数据发布到 TLS 1.2 端点。我希望在 App.config 中指定 SecurityProtocol,而不是在源代码中进行硬编码,并且不想将机器的注册表设置为禁用 TLS 1.1。

如果您未指定 SecurityProtocol,则使用底层操作系统协议,但它们似乎默认为最不安全而不是最安全。因为我从机器上运行了多个服务,所以我无法将操作系统设置为仅使用 TLS1.2,但我仍然希望这个特定的客户端使用 TLS 1.2,并且当 TLS 1.3 出现时,可以通过应用程序特定的配置对其进行修改。

这个问题通过代码解释了如何做到这一点:How to specify SSL protocol to use for WebClient class

这个问题解释了如何通过整个机器的注册表设置来做到这一点:Are there .NET implementation of TLS 1.2?

// this is what I want to avoid
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocol.Tls12;

System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(url);

using (System.IO.StreamWriter sw = new System.IO.StreamWriter(request.GetRequestStream()))
{
    sw.write(json);
}

System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
using System.IO.StreamReader sr = new System.IO.StreamReader(response.GetResponseStream()))
{
    content = sr.ReadToEnd();
}

目前我的 App.config 中没有此客户端的任何内容,但这就是我想要更改的内容。

我发现system.serviceModel里面有一个sslStreamSecurity元素,但我相信这是给ServiceReferences的,不是普通的HttpWebRequest。我相信 system.net 涵盖了这一点,但我找不到等价物。

<system.serviceModel>
  <bindings>
    <customBinding>
      <binding name="myBinding">
        <sslStreamSecurity sslProtocls="Tls12">
      </binding>
    </customBinding>
  </bindings>
  <client>
    <endpoint address="https://myserver.com" binding="customBinding" bindingConfiguration="myBinding" name="myEndpoint" />
  </client>
</system.ServiceModel>

我对使用 HttpWebRequest/HttpWebResponse 以外的东西持相当开放的态度,但不想安装第三方包。我从System.Net.Http.HttpClient 开始,它似乎比 HttpWebRequest 更新,但很快遇到了同样的问题。

【问题讨论】:

    标签: .net httpwebrequest webclient app-config dotnet-httpclient


    【解决方案1】:

    只要您在≥.net-4.6 上运行它,就可以通过编辑app.config 来更改针对<.net-4.6 href="https://docs.microsoft.com/dotnet/framework/network-programming/tls##configuring-security-via-appcontext-switches-for-net-framework-46-or-later-versions" rel="nofollow" target="_blank">“Transport Layer Security (TLS) best practices with the .NET Framework” 中有记录。

    当 Microsoft 开发 .net-4.6 作为 .net-4.5 的就地替代品时,他们希望进行行为更改,包括错误修复、安全改进等。但他们不想破坏针对 .net-4.5 的应用程序它依赖于旧的行为——甚至是有缺陷的行为(旧代码依赖于有缺陷的行为是很常见的,微软的 .net 团队为了兼容性而有意保留错误)。要做到这一点,从 .net-4.6 开始并继续后续版本,每个预期会导致兼容性问题的新行为更改都放置在启用旧行为的开关后面,默认为 true。在编译时,目标框架存储在程序集中。当运行时加载入口点的程序集时,它会检查目标版本,然后自动为目标 .net 版本预设其兼容性开关。

    如果您无法重新定位或重新编译您的应用程序,您可以通过在通常命名为«ExecutableName».exe.configapp.config 中添加或编辑&lt;AppContextSwitchOverrides/&gt; 来手动指定这些兼容性开关的值。 .net-4.7 中添加了开关DontEnableSystemDefaultTlsVersions,它支持使用系统提供的 TLS 策略。 .net-4.6 中添加了开关 DontEnableSchUseStrongCrypto,它增加了对 TLS 1.2 的支持。

    <?xml version="1.0"?>
    <configuration>
      <runtime>
        <!--
          Support connecting to servers which require modern TLS protocols.
    
          DontEnableSystemDefaultTlsVersions=false is sufficient if running on ≥.net-4.7
          which supports using the system-provided TLS versions/policies.
          DontEnableSchUseStrongCrypto is required if running on .net-4.6 which defaults
          to newer versions of TLS but doesn’t support following system updates/policies.
         -->
        <AppContextSwitchOverrides value="Switch.System.Net.DontEnableSystemDefaultTlsVersions=false;Switch.System.Net.DontEnableSchUseStrongCrypto=false"/>
      </runtime>
    </configuration>
    

    【讨论】:

      【解决方案2】:

      使用协议名称而不是整数代码的示例。

      string securityProtocol = ConfigurationManager.AppSettings["SecurityProtocol"].ToString();
      
      try
      {
          System.Net.ServicePointManager.SecurityProtocol = (System.Net.SecurityProtocolType)Enum.Parse(typeof(System.Net.SecurityProtocolType), securityProtocol);
      }
      catch (Exception ex)
      {
          Console.WriteLine("Could not setup SecurityProtocol. Try a different integer value: " + ex.Message);
          foreach (System.Net.SecurityProtocolType protocolType in Enum.GetValues(typeof(System.Net.SecurityProtocolType)))
          {
              Console.WriteLine(string.Foramt("SecurityProtocol: {0} - {1}", protocolType.ToString(), (int)protocolType));
          }
      }
      

      对于 App.Config

      <appSettings>
          <add key="SecurityProtocol" value="Tls12" />
      </appSettings>
      

      【讨论】:

        【解决方案3】:

        现在我已经在 App.config 中放置了一个整数值,它指定了要设置 System.Net.ServicePointManager.SecurityProtocol 的枚举值。我仍然认为可能有一种更优雅的方式来做到这一点,并期待其他答案。 https://stackoverflow.com/a/35325333/5221761

        引导我朝这个方向发展
        int securityProtocol = Convert.ToInt32(ConfigurationManager.AppSettings["SecurityProtocol"]);
        
        try
        {
            System.Net.ServicePointManager.SecurityProtocol = (System.Net.SecurityProtocolType)securityProtocol;
        }
        catch(Exception ex)
        {
            Console.WriteLine("Could not setup SecurityProtocol. Try a different integer value: " + ex.Message);
            foreach (System.Net.SecurityProtocolType protocolType in Enum.GetValues(typeof(System.Net.SecurityProtocolType)))
            {
                Console.WriteLine(string.Foramt("SecurityProtocol: {0} - {1}", protocolType.ToString(), (int)protocolType));
            }
        }
        

        App.config:

        <appSettings>
            <add key="SecurityProtocol" value="3072" />
        </appSettings>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-08-18
          • 1970-01-01
          • 2011-10-28
          • 2015-11-22
          • 2011-07-28
          相关资源
          最近更新 更多