Apache HttpClient 配置 SSL 证书指南
概述
在使用 Apache HttpClient 进行 HTTPS 请求时,有时需要配置自定义的 SSL 证书以建立安全连接。本文介绍如何为 HttpClient 配置 SSL 证书,特别是从 classpath 加载 .crt 证书文件的场景。
应用场景
- 连接使用自签名证书的服务器
- 企业内网环境中的 HTTPS 服务调用
- 需要双向认证的安全连接
- 数据库(如 Doris)的 SSL 连接
核心实现步骤
1. 添加 Maven 依赖
xml
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
2. 加载证书文件
从 classpath 读取证书文件并生成证书对象:
java
// 从 resources 目录读取 .crt 证书文件
InputStream is = new ClassPathResource("certs/server.crt").getInputStream();
// 生成 X509 证书对象
Certificate cert = CertificateFactory.getInstance("X.509")
.generateCertificate(is);
3. 构建 KeyStore
将证书装入 Java KeyStore:
java
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
trustStore.setCertificateEntry("my_cert", cert);
4. 创建 SSLContext
使用 KeyStore 构建 SSL 上下文:
java
SSLContext sslContext = SSLContextBuilder.create()
.loadTrustMaterial(trustStore, null)
.build();
5. 配置 HttpClient
将 SSL 配置注册到连接管理器:
java
// 创建 SSL 连接工厂
SSLConnectionSocketFactory sslSocketFactory =
new SSLConnectionSocketFactory(sslContext);
// 注册 HTTP 和 HTTPS 协议
Registry<ConnectionSocketFactory> registry =
RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", sslSocketFactory)
.build();
// 创建连接管理器
PoolingHttpClientConnectionManager connManager =
new PoolingHttpClientConnectionManager(registry);
// 构建 HttpClient
CloseableHttpClient httpClient = HttpClients.custom()
.setConnectionManager(connManager)
.build();
完整示例代码
java
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import javax.net.ssl.SSLContext;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
public class HttpClientSSLConfig {
public CloseableHttpClient createSSLHttpClient(String certPath) throws Exception {
// 1. 加载证书
InputStream is = new ClassPathResource(certPath).getInputStream();
Certificate cert = CertificateFactory.getInstance("X.509")
.generateCertificate(is);
// 2. 构建 KeyStore
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null, null);
trustStore.setCertificateEntry("server_cert", cert);
// 3. 创建 SSLContext
SSLContext sslContext = SSLContextBuilder.create()
.loadTrustMaterial(trustStore, null)
.build();
// 4. 配置连接管理器
SSLConnectionSocketFactory sslSocketFactory =
new SSLConnectionSocketFactory(sslContext);
Registry<ConnectionSocketFactory> registry =
RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", sslSocketFactory)
.build();
PoolingHttpClientConnectionManager connManager =
new PoolingHttpClientConnectionManager(registry);
// 5. 构建 HttpClient
return HttpClients.custom()
.setConnectionManager(connManager)
.build();
}
}
使用示例
java
// 创建配置了 SSL 的 HttpClient
CloseableHttpClient httpClient = createSSLHttpClient("certs/server.crt");
// 发起 HTTPS 请求
HttpGet request = new HttpGet("https://example.com/api");
CloseableHttpResponse response = httpClient.execute(request);
// 处理响应
int statusCode = response.getStatusLine().getStatusCode();
String responseBody = EntityUtils.toString(response.getEntity());
注意事项
- 证书路径 :确保证书文件放在
src/main/resources目录下 - 异常处理:生产环境中需要妥善处理各类异常(IOException、CertificateException 等)
- 连接池配置:可根据实际需求配置连接池参数(最大连接数、超时时间等)
- 资源释放:使用完毕后记得关闭 HttpClient 和 Response 对象
- 证书格式 :支持
.crt、.pem等 X.509 格式证书
常见问题
Q: 如何配置双向认证(mTLS)?
需要同时配置 trustStore(服务端证书)和 keyStore(客户端证书):
java
SSLContext sslContext = SSLContextBuilder.create()
.loadTrustMaterial(trustStore, null)
.loadKeyMaterial(keyStore, keyPassword)
.build();
Q: 如何跳过证书验证(仅用于开发环境)?
java
SSLContext sslContext = SSLContextBuilder.create()
.loadTrustMaterial(null, (chain, authType) -> true)
.build();
警告:生产环境中不要跳过证书验证!
总结
通过以上步骤,我们可以为 Apache HttpClient 配置自定义 SSL 证书,实现安全的 HTTPS 通信。这种方式特别适用于企业内网环境或需要使用自签名证书的场景。
参考资源: