You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Apache HttpClient配置ca.pem、key.pem和cert.pem证书

配置HttpClient加载PEM格式证书访问服务

要让HttpClient正确使用ca.pem、key.pem和cert.pem三个PEM文件,需要修改现有代码,正确加载证书和私钥到SSL上下文,而非简单信任所有证书。以下是具体实现方案:

核心步骤

  • 加载CA证书到信任库,用于验证服务端证书合法性
  • 加载客户端证书和私钥到密钥库,用于服务端验证客户端身份
  • 基于信任库和密钥库构建合规的SSLContext
  • 配置HttpClient使用该SSLContext,保留原有拦截器等业务配置

修改后的完整代码

import org.apache.http.HttpRequestInterceptor;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.ssl.SSLContextBuilder;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;

import java.io.FileInputStream;
import java.io.FileReader;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import org.bouncycastle.openssl.PEMParser;
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;

public class HttpClientCertConfig {

    public HttpComponentsClientHttpRequestFactory createCertEnabledRequestFactory() throws Exception {
        // 初始化证书工厂
        CertificateFactory certFactory = CertificateFactory.getInstance("X.509");

        // 加载CA证书并构建信任库
        X509Certificate caCert = (X509Certificate) certFactory.generateCertificate(
                new FileInputStream(getClass().getResource("/certs/ca.pem").getPath()));
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        trustStore.load(null);
        trustStore.setCertificateEntry("ca-trust-cert", caCert);

        // 加载客户端证书
        X509Certificate clientCert = (X509Certificate) certFactory.generateCertificate(
                new FileInputStream(getClass().getResource("/certs/cert.pem").getPath()));

        // 加载客户端私钥(依赖BouncyCastle解析PEM格式私钥)
        PEMParser pemParser = new PEMParser(new FileReader(getClass().getResource("/certs/key.pem").getPath()));
        Object keyObj = pemParser.readObject();
        JcaPEMKeyConverter keyConverter = new JcaPEMKeyConverter();
        PrivateKey clientPrivateKey = keyConverter.getPrivateKey((org.bouncycastle.asn1.pkcs.PrivateKeyInfo) keyObj);

        // 构建客户端密钥库
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(null);
        // 若私钥有密码,替换第二个参数为实际密码字符串
        keyStore.setKeyEntry("client-auth-key", clientPrivateKey, "".toCharArray(), new X509Certificate[]{clientCert});

        // 构建带证书验证的SSLContext
        SSLContext sslContext = new SSLContextBuilder()
                .loadTrustMaterial(trustStore, null) // 仅信任指定CA证书
                .loadKeyMaterial(keyStore, "".toCharArray()) // 加载客户端身份证书
                .build();

        // 配置HttpClient
        CloseableHttpClient httpClient = HttpClients.custom()
                .setSSLContext(sslContext)
                // 生产环境建议移除该配置,启用默认域名验证逻辑,避免安全风险
                .setSSLHostnameVerifier(new NoopHostnameVerifier())
                .addInterceptorFirst((HttpRequestInterceptor) (httpRequest, httpContext) -> {
                    httpRequest.setHeader("Content-Type", "application/xml");
                })
                .build();

        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
        requestFactory.setHttpClient(httpClient);
        return requestFactory;
    }
}

依赖说明

解析PEM格式私钥需引入BouncyCastle依赖(Maven示例):

<dependency>
    <groupId>org.bouncycastle</groupId>
    <artifactId>bcpkix-jdk15on</artifactId>
    <version>1.70</version>
</dependency>

关键注意事项

  • 私钥若设置了密码,需将代码中的空字符串""替换为实际密码
  • 生产环境必须移除NoopHostnameVerifier,启用默认的域名验证,防止中间人攻击
  • 确保三个PEM文件放置在类路径下的certs目录,或根据实际路径调整资源读取逻辑

内容的提问来源于stack exchange,提问作者Robert Wilson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 00:13:07