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版本。
0 评论