如何在Apache HttpClient中設置TLS版本
1、簡介
Apache HttpClient是一個底層、輕量級的客戶端HTTP庫,用於與HTTP伺服器進行通訊。
在本教程中,我們將學習如何在使用HttpClient時配置支援的傳輸層安全(TLS)版本。
我們將首先概述TLS版本協商如何在客戶端和伺服器之間工作。
之後,我們將看看在使用HttpClient時配置支援的TLS版本的三種不同方式。
2、TLS版本協商
TLS是一種互聯網協議,可在兩方之間提供安全、可信的通訊。它封裝了像HTTP這樣的應用層協議。
TLS協議自1999年首次發布以來已多次修訂。
因此,客戶端和伺服器在建立新連接時,首先就他們將使用的TLS版本達成一致非常重要。
TLS版本在客戶端和伺服器交換hello消息後達成一致:
- 客戶端發送支援的 TLS 版本列表。
- 伺服器選擇一個並在響應中包含所選版本。
- 客戶端和伺服器使用所選版本繼續連接設置。
由於存在降級攻擊的風險,因此正確配置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版本。
原文://www.baeldung.com/apache-httpclient-tls
翻譯:碼農熊貓
更多技術乾貨,請訪問我的個人網站//pinmost.com,或關注公眾號【碼農熊貓】

