Dot-Net

通過 App.config 為 System.Net.HttpWebRequest 指定 SSL/TLS

  • May 1, 2019

我需要將 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 更新的路徑,但很快遇到了同樣的問題。

app.config只要您在 ≥.net-4.6 上執行它,就可以更改針對 <.net-4.6 的應用程序的 TLS 設置,而無需通過編輯它來重新編譯它。這在“使用 .NET Framework 的傳輸層安全性 (TLS) 最佳實踐”中進行了說明

當 Microsoft 開發 .net-4.6 作為 .net-4.5 的就地替代品時,他們希望進行行為更改,包括錯誤修復、安全改進等。但他們不想破壞依賴於 .net-4.5 的應用程序舊行為——甚至是有缺陷的行為(舊程式碼依賴於有缺陷的行為是很常見的,Microsoft 的 .net 團隊非常關心為了兼容性而有目的地保留缺陷)。為此,從 .net-4.6 開始並繼續後續版本,每個預期會導致兼容性問題的新行為更改都放置在啟用舊行為的開關後面,預設為true. 在編譯時,目標框架儲存在程序集中。當執行時載入入口點的程序集時,它會檢查目標版本,然後自動為目標 .net 版本預設其兼容性開關。

如果您無法重新定位或重新編譯您的應用程序,您可以通過添加或編輯通常命名&lt;AppContextSwitchOverrides/&gt;為. 該開關是在 .net-4.7 中添加的,它支持使用系統提供的 TLS 策略。該開關是在 .net-4.6 中添加的,它增加了對 TLS 1.2 的支持。app.config``«ExecutableName».exe.config``DontEnableSystemDefaultTlsVersions``DontEnableSchUseStrongCrypto

&lt;?xml version="1.0"?&gt;
&lt;configuration&gt;
 &lt;runtime&gt;
   &lt;!--
     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.
    --&gt;
   &lt;AppContextSwitchOverrides value="Switch.System.Net.DontEnableSystemDefaultTlsVersions=false;Switch.System.Net.DontEnableSchUseStrongCrypto=false"/&gt;
 &lt;/runtime&gt;
&lt;/configuration&gt;

使用協議名稱而不是整數程式碼的範例。

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

&lt;appSettings&gt;
   &lt;add key="SecurityProtocol" value="Tls12" /&gt;
&lt;/appSettings&gt;

引用自:https://stackoverflow.com/questions/45492000