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


参考资源

相关推荐
小bo波39 分钟前
枚举实战
java·设计模式·枚举·后端开发·代码重构
夜微凉41 小时前
三、Spring
java·后端·spring
橘右今1 小时前
2026 Java后端高频面试宝典
java·开发语言·面试
xyzzklk2 小时前
解决Salesforce无法向外发送邮件
android·java·开发语言·网络·crm·salesforce·客户关系管理
biubiubiu07062 小时前
SpringBoot关于外部化配置
java·spring boot·spring
zzz_23682 小时前
【Spring】面试突击系列(二):SpringBoot 入门与自动配置原理
java·spring boot·spring
Full Stack Developme3 小时前
Spring AOP 与 AspectJ
java·后端·spring
快乐的木子李3 小时前
最新版Maven免安装配置教程
java·maven
wuminyu4 小时前
Java锁机制之Java对象重量级锁源码剖析
java·linux·c语言·jvm·c++
艾利克斯冰4 小时前
Java设计模式-创建型设计模式
java