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 通信。这种方式特别适用于企业内网环境或需要使用自签名证书的场景。


参考资源:

相关推荐
明天也要努力学习8 小时前
HTTP 协议的基本格式和 fiddler 的用法
网络协议·http·fiddler
学长毕设8 小时前
基于SpringBoot的实验室资产管理系统
java·spring boot·后端
zzu123zsw9 小时前
从臃肿的模板调用到声明式契约:深入 UniHttp 动态代理与多渠道生命周期扩展
java·spring boot·microsoft·unihttp
源码集结号10 小时前
云诊所门诊系统源码,基于SpringBoot+Vue.js架构,支持多租户设计与Docker容器化部署
java·spring boot·源码·医院信息系统·门诊系统·诊所系统
论文复现现场10 小时前
WRF、FEA 能用 L40S 加速吗?求解器检查、断点恢复与长期运行
java·数据库·算法·wrf·有限元分析·gpu计算·断点续算
啃瓜子的松鼠11 小时前
泛微OAe9-后端二开异步调用
java
秋天的怀念_David12 小时前
第二十一夜 · 数字黑洞与西西弗斯的惩罚
java·程序人生·算法
外收内放12 小时前
Python基础语法练习题(73)
java·前端·python
Wang's Blog12 小时前
Java 项目实战: 交友项目 - 环信后台发送消息测试
java·交友
用户37215742613512 小时前
Java 操作 Word 脚注和尾注:添加、读取与删除
java