如何在Apache HttpClient中設置TLS版本
- HttpClient
- java
1.簡介
Apache HttpClient是一個低級,輕量級的客戶端HTTP庫,用於與HTTP服務器進行通信。在本教程中,我們將學習如何在使用HttpClient時配置支持的傳輸層安全性(TLS)版本。我們將首先概述客戶端和服務器之間TLS版本協商的工作方式。之後,我們將研究使用HttpClient時配置受支持的TLS版本的三種不同方式。
2. TLS版本協商
TLS是一種互聯網協議,可在兩方之間提供安全,可信任的通信。它封裝了諸如HTTP之類的應用程序層協議。自從1999年首次發布以來,TLS協議已進行了多次修訂。因此,對於客戶端和服務器,首先要商定在建立新連接時將使用哪個版本的TLS,這一點很重要。客戶端和服務器交換問候消息後,將同意TLS版本:
- 客戶端發送支持的TLS版本的列表。
- 服務器選擇一個,並在響應中包括所選版本。
- 客戶端和服務器使用所選版本繼續進行連接設置。
正確配置Web客戶端支持的TLS版本非常重要,因為存在降級攻擊的風險。請注意,為了使用最新版本的TLS(TLS 1.3),我們必須使用Java 11或更高版本。
3.靜態設置TLS版本
3.1 SSLConnectionSocketFactory
讓我們用HttpClientBuilder
通過暴露HttpClients#custom
構建器方法,以定制我們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進行通信。請注意,在4.3之前的Apache HttpClient版本中,該類稱為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.example.com.
SSLSocket
之前插入自定義邏輯的功能,我們的應用程序現在可以自定義TLS通信詳細信息。
5.結論
在本文中,我們研究了使用Apache HttpClient庫時配置受支持的TLS版本的三種不同方式。我們已經了解瞭如何為所有連接或基於每個連接設置TLS版本。