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版本。
原文:https://www.baeldung.com/apache-httpclient-tls
翻譯:碼農熊貓
更多技術乾貨,請訪問我的個人網站https://pinmost.com,或關注公眾號【碼農熊貓】