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

无需导入证书到JVM密钥库,配置带CA及客户端证书的自定义RestTemplate

在Spring Boot中为RestTemplate添加CA证书(PEM文件)

一、修改现有RestTemplate配置,加载CA证书

你的现有代码仅加载了客户端证书作为信任材料,要添加CA证书,需要将CA证书导入信任库,再结合客户端证书构建SSLContext。具体步骤如下:

1. 先添加依赖(解析PEM证书用)

如果用Maven,添加BouncyCastle依赖来解析PEM格式的CA证书:

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

2. 修改RestTemplate Bean代码

import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
import org.bouncycastle.openssl.PEMParser;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import java.io.InputStreamReader;
import java.security.KeyStore;
import java.security.cert.X509Certificate;

@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate() throws Exception {
        // 1. 加载客户端证书(原有逻辑,假设是PKCS12格式)
        String clientCertPath = "classpath:client-cert.p12";
        char[] clientCertPassword = "your-client-password".toCharArray();
        
        // 2. 从资源文件夹加载CA PEM证书并解析
        ClassPathResource caResource = new ClassPathResource("ca-cert.pem");
        PEMParser pemParser = new PEMParser(new InputStreamReader(caResource.getInputStream()));
        X509CertificateHolder caCertHolder = (X509CertificateHolder) pemParser.readObject();
        X509Certificate caCert = new JcaX509CertificateConverter().getCertificate(caCertHolder);
        pemParser.close();
        
        // 3. 创建包含CA证书的信任库
        KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
        trustStore.load(null, null);
        trustStore.setCertificateEntry("custom-ca", caCert);
        
        // 4. 初始化信任管理器
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(trustStore);
        X509TrustManager trustManager = (X509TrustManager) trustManagerFactory.getTrustManagers()[0];
        
        // 5. 加载客户端证书作为密钥材料(双向认证用)
        KeyStore keyStore = KeyStore.getInstance("PKCS12");
        keyStore.load(new ClassPathResource(clientCertPath).getInputStream(), clientCertPassword);
        
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, clientCertPassword);
        
        // 6. 构建SSLContext,同时配置密钥管理器(客户端证书)和信任管理器(CA证书)
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(keyManagerFactory.getKeyManagers(), new X509TrustManager[]{trustManager}, null);
        
        // 7. 组装HttpClient和RestTemplate
        SSLConnectionSocketFactory sslConFactory = new SSLConnectionSocketFactory(sslContext);
        CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslConFactory).build();
        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
        
        return new RestTemplate(requestFactory);
    }
}

这段代码会让RestTemplate同时使用客户端证书做双向认证,并且信任指定CA签发的服务端证书。

二、Spring Boot中的其他实现方式

1. 全局SSL配置(application.properties)

如果希望整个应用都信任该CA证书,可以把CA证书导入到JKS格式的信任库中,然后在application.properties配置全局SSL参数:

# 信任库路径(资源文件夹下的truststore.jks)
server.ssl.trust-store=classpath:truststore.jks
server.ssl.trust-store-password=your-truststore-password
server.ssl.trust-store-type=JKS

注意:这种方式是全局生效的,会影响应用内所有SSL请求,不是仅针对单个RestTemplate。

2. 结合RestTemplateBuilder简化配置

如果需要利用Spring Boot的RestTemplateBuilder做额外配置(比如超时、拦截器),可以这样整合自定义SSL:

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) throws Exception {
    // 先按照前面的步骤构建好sslContext
    SSLConnectionSocketFactory sslConFactory = new SSLConnectionSocketFactory(sslContext);
    CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(sslConFactory).build();
    HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
    
    // 用builder整合自定义请求工厂,同时可以添加其他配置
    return builder.requestFactory(() -> requestFactory)
                  .setConnectTimeout(Duration.ofSeconds(10))
                  .build();
}

注意事项

  • 如果CA证书是链式结构(包含中间证书),需要把所有层级的证书都加入到信任库中。
  • 请根据你的Spring Boot版本选择兼容的BouncyCastle版本,避免依赖冲突。
  • 如果客户端证书也是PEM格式,同样可以用BouncyCastle解析后导入到KeyStore中使用。

内容的提问来源于stack exchange,提问作者Victoria Agafonova

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 18:36:42