如何在Apache HttpClient中設置TLS版本


1、簡介

Apache HttpClient是一個底層、輕量級的客戶端HTTP庫,用於與HTTP服務器進行通信。
在本教程中,我們將學習如何在使用HttpClient時配置支持的傳輸層安全(TLS)版本。
我們將首先概述TLS版本協商如何在客戶端和服務器之間工作。
之后,我們將看看在使用HttpClient時配置支持的TLS版本的三種不同方式

2、TLS版本協商

TLS是一種互聯網協議,可在兩方之間提供安全、可信的通信。它封裝了像HTTP這樣的應用層協議。
TLS協議自1999年首次發布以來已多次修訂。
因此,客戶端和服務器在建立新連接時,首先就他們將使用的TLS版本達成一致非常重要。
TLS版本在客戶端和服務器交換hello消息后達成一致:

  1. 客戶端發送支持的 TLS 版本列表。
  2. 服務器選擇一個並在響應中包含所選版本。
  3. 客戶端和服務器使用所選版本繼續連接設置。

由於存在降級攻擊的風險,因此正確配置Web客戶端支持的TLS版本非常重要。
請注意,為了使用最新版本的TLS(TLS 1.3),我們必須使用Java 11或更高版本

3、固定設置TLS版本

3.1、SSLConnectionSocketFactory

讓我們通過HttpClients#custom定制構建方法提供的HttpClientBuilder,來定制我們的HTTPClient配置。
此構建器模式允許我們傳入我們自己的SSLConnectionSocketFactory,它將根據一組所需支持的TLS版本進行實例化:

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
  SSLContexts.createDefault(),
  new String[] { "TLSv1.2", "TLSv1.3" },
  null,
  SSLConnectionSocketFactory.getDefaultHostnameVerifier());

CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();

返回的Httpclient對象現在可以執行HTTP請求了。
通過在SSLConnectionSocketFactory構造函數中顯式設置支持的協議,客戶端將僅支持通過TLS 1.2或TLS 1.3的通信。
請注意,在 Apache HttpClient 4.3 之前的版本中,該類稱為SSLSocketFactory

3.2、Java運行時參數

另外,我們可以使用Java的https.protocols系統屬性配置支持的TLS版本。
此方法可以防止必須將值硬編碼到應用程序代碼中。
相反,我們將配置HttpClient以在設置連接時使用該系統屬性。
HttpClient API提供了兩種方法來實現。第一個是通過HttpClients#createSystem

CloseableHttpClient httpClient = HttpClients.createSystem();

如果需要更多的客戶端配置,我們可以使用builder方法代替:

CloseableHttpClient httpClient = HttpClients.custom().useSystemProperties().build();

這兩種方法都告訴HttpClient在連接配置期間使用系統屬性。
這允許我們在應用程序運行時使用命令行參數設置所需的TLS版本。例如:

$ java -Dhttps.protocols=TLSv1.1,TLSv1.2,TLSv1.3 -jar webClient.jar

4、動態設置TLS版本

還可以根據主機名和端口等連接詳細信息設置TLS版本。我們將擴展SSLConnectionSocketFactory並覆蓋prepareSocket方法。
客戶端會在啟動新連接之前調用prepareSocket方法,這將可以讓我們在每個連接的基礎上決定使用哪些TLS協議。
也可以啟用對舊TLS版本的支持,但前提是遠程主機具有特定的子域:

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(SSLContexts.createDefault()){

    @Override
    protected void prepareSocket(SSLSocket socket) {

        String hostname = socket.getInetAddress().getHostName();
        if (hostname.endsWith("internal.system.com")){
            socket.setEnabledProtocols(new String[] { "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3" });
        }
        else {
            socket.setEnabledProtocols(new String[] {"TLSv1.3"});
        }
    }
};
CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslsf).build();

在上面的示例中,prepareSocket方法首先獲取SSLSocket將連接到的遠程主機名,然后使用主機名來確定要啟用的TLS協議。
現在,我們的HTTP客戶端將對每個請求強制執行TLS 1.3,除了目標主機名的格式為*.internal.system.com
由於能夠在創建新SSLSocket之前插入自定義邏輯,我們的應用程序現在可以自定義TLS通信的詳細信息。

5、結論

在本文中,我們研究了在使用Apache HttpClient庫時配置支持的TLS版本的三種不同方式。
我們已經了解了如何為所有連接或基於每個連接設置TLS版本。

原文:https://www.baeldung.com/apache-httpclient-tls

翻譯:碼農熊貓

更多技術干貨,請訪問我的個人網站https://pinmost.com,或關注公眾號【碼農熊貓】


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM