Spring Boot中使用RestTemplate实现带证书的HTTPS调用
用Spring Boot的RestTemplate实现指定HTTPS客户端证书调用
核心配置对应
你要实现的curl命令包含几个关键要求:
- 强制使用TLSv1.2协议
- 信任自定义CA证书(对应
--cacert参数) - 携带客户端证书(对应
--cert参数)及PKCS8格式的私钥(对应--key参数)
以下是具体实现步骤:
1. 构建带SSL配置的RestTemplate
需要先加载证书和私钥,生成符合要求的SSLContext,再注入到RestTemplate的请求工厂中:
import org.springframework.http.client.SimpleClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; import javax.net.ssl.*; import java.io.FileInputStream; import java.security.*; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64; public class SslRestTemplateConfig { public RestTemplate createSslRestTemplate() throws Exception { // 1. 加载CA证书,构建信任库 CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); X509Certificate caCert; try (FileInputStream fis = new FileInputStream("/etc/pki_service/ca/cacerts.pem")) { caCert = (X509Certificate) certFactory.generateCertificate(fis); } KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(null, null); trustStore.setCertificateEntry("ca-trust-cert", caCert); // 2. 加载客户端证书 X509Certificate clientCert; try (FileInputStream fis = new FileInputStream("/etc/identity/client/certificates/client.pem")) { clientCert = (X509Certificate) certFactory.generateCertificate(fis); } // 3. 加载PKCS8格式的私钥 String privateKeyRaw = new String(java.nio.file.Files.readAllBytes(java.nio.file.Paths.get("/etc/identity/client/keys/client-key.pkcs8"))) .replace("-----BEGIN PRIVATE KEY-----", "") .replace("-----END PRIVATE KEY-----", "") .replaceAll("\\s", ""); byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyRaw); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes); PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec); // 4. 构建客户端密钥库 KeyStore clientKeyStore = KeyStore.getInstance(KeyStore.getDefaultType()); clientKeyStore.load(null, null); // 若私钥有密码,替换第三个参数为密码字符数组,比如"your-pass".toCharArray() clientKeyStore.setKeyEntry("client-auth-key", privateKey, new char[0], new Certificate[]{clientCert}); // 5. 生成SSLContext,指定TLSv1.2 TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(trustStore); KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); keyManagerFactory.init(clientKeyStore, new char[0]); SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); // 6. 配置RestTemplate请求工厂 SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); requestFactory.setSslContext(sslContext); return new RestTemplate(requestFactory); } }
2. 注册RestTemplate到Spring容器
在配置类中把上述RestTemplate注册为Bean,方便依赖注入:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class AppConfig { @Bean public RestTemplate sslRestTemplate() throws Exception { return new SslRestTemplateConfig().createSslRestTemplate(); } }
3. 使用RestTemplate发起请求
注入配置好的RestTemplate后,即可正常调用目标接口:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.client.RestTemplate; @Component public class HttpsClient { @Autowired private RestTemplate sslRestTemplate; public String callTargetServer() { String targetUrl = "https://server.com"; return sslRestTemplate.getForObject(targetUrl, String.class); } }
注意事项
- 确保应用程序对证书、私钥文件有读取权限,否则会抛出IO异常
- 生产环境建议通过
@Value注入文件路径,避免硬编码,比如@Value("${ssl.ca-cert-path}") - 若需要连接池、超时等更灵活的配置,可以改用
HttpComponentsClientHttpRequestFactory(基于Apache HttpClient),配置逻辑类似
内容的提问来源于stack exchange,提问作者Joy
相关产品推荐
相关产品推荐

