Apache HttpClient 配置 SSL 证书指南

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());

注意事项

  1. 证书路径 :确保证书文件放在 src/main/resources 目录下
  2. 异常处理:生产环境中需要妥善处理各类异常(IOException、CertificateException 等)
  3. 连接池配置:可根据实际需求配置连接池参数(最大连接数、超时时间等)
  4. 资源释放:使用完毕后记得关闭 HttpClient 和 Response 对象
  5. 证书格式 :支持 .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 通信。这种方式特别适用于企业内网环境或需要使用自签名证书的场景。


参考资源

相关推荐
mOok ONSC1 天前
SpringBoot项目中读取resource目录下的文件(六种方法)
spring boot·python·pycharm
lay_liu1 天前
springboot 文件下载
java·spring boot·后端
Flittly1 天前
【SpringAIAlibaba新手村系列】(11)Embedding 向量化与向量数据库
java·笔记·spring·ai·springboot
workflower1 天前
AI制造-推荐初始步骤
java·开发语言·人工智能·软件工程·制造·需求分析·软件需求
ACGkaka_1 天前
SimpleDateFormat 线程安全问题及修复方案
java·jvm·安全
smileNicky1 天前
Spring AI系列之Tool Calling实战指南
人工智能·spring boot·spring
leo_messi941 天前
多线程(五) -- 并发工具(二) -- J.U.C并发包(八) -- CompletableFuture组合式异步编程
android·java·c语言
m0_380113841 天前
SpringBoot创建动态定时任务的几种方式
java·spring boot·spring
Gofarlic_OMS1 天前
SolidEdge专业许可证管理工具选型关键评估标准
java·大数据·运维·服务器·人工智能