如何用Java Spring Boot复现Postman中发送.cer和.key文件的场景
用Java Spring Boot实现客户端证书认证(基于X.509证书与RSA密钥)
场景说明
我持有X.509格式的.cer证书文件,以及用于客户端数据交互的RSA私钥.key文件,希望用Java Spring Boot复现Postman中配置客户端证书调用接口的场景(对应截图场景:配置客户端证书、私钥完成接口请求)。
实现步骤
1. 准备证书与密钥文件
- 将
.cer和.key文件放入Spring Boot项目的src/main/resources目录,或指定明确的绝对路径。 - 若密钥设置了密码,需提前留存该密码。
2. 配置带客户端证书的RestTemplate
创建配置类,构建支持客户端证书认证的RestTemplate实例:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.conn.ssl.SSLContextBuilder; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import java.io.FileInputStream; import java.security.KeyStore; import java.security.PrivateKey; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.security.spec.PKCS8EncodedKeySpec; import java.security.KeyFactory; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Base64; @Configuration public class RestTemplateConfig { @Bean public RestTemplate clientCertRestTemplate() throws Exception { // 加载X.509证书 CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); Certificate cert = certFactory.generateCertificate(new FileInputStream("src/main/resources/client.cer")); // 加载RSA私钥(去除PEM格式头尾与空白字符) String privateKeyContent = new String(Files.readAllBytes(Paths.get("src/main/resources/client.key"))) .replace("-----BEGIN PRIVATE KEY-----", "") .replace("-----END PRIVATE KEY-----", "") .replaceAll("\\s", ""); byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyContent); PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes); PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec); // 创建密钥库并存入证书与私钥 KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); keyStore.load(null); keyStore.setCertificateEntry("client-cert", cert); keyStore.setKeyEntry("client-key", privateKey, "你的密钥密码".toCharArray(), new Certificate[]{cert}); // 构建SSL上下文 SSLContextBuilder sslContextBuilder = SSLContextBuilder.create() .loadKeyMaterial(keyStore, "你的密钥密码".toCharArray()); // 创建SSL连接工厂 SSLConnectionSocketFactory sslSocketFactory = new SSLConnectionSocketFactory( sslContextBuilder.build(), new String[]{"TLSv1.2"}, null, SSLConnectionSocketFactory.getDefaultHostnameVerifier()); // 构建HttpClient实例 CloseableHttpClient httpClient = HttpClients.custom() .setSSLSocketFactory(sslSocketFactory) .build(); ClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient); return new RestTemplate(requestFactory); } }
3. 调用目标接口示例
在业务类中注入配置好的RestTemplate,发起带证书的请求:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; @Service public class ApiClientService { private final RestTemplate clientCertRestTemplate; @Autowired public ApiClientService(RestTemplate clientCertRestTemplate) { this.clientCertRestTemplate = clientCertRestTemplate; } public String callSecureApi() { String targetApiUrl = "https://你的目标接口地址"; // 根据接口需求选择GET/POST等请求方式 return clientCertRestTemplate.getForObject(targetApiUrl, String.class); } }
4. 关键注意事项
- 若目标服务器的CA证书未被JVM信任,需额外配置信任库,将服务器CA证书加入信任链,避免SSL握手失败。
- 确保私钥为PKCS#8格式(PEM头为
-----BEGIN PRIVATE KEY-----),若为PKCS#1格式(头为-----BEGIN RSA PRIVATE KEY-----),可通过OpenSSL转换:openssl pkcs8 -topk8 -inform PEM -in client.key -outform PEM -nocrypt - 代码中的文件路径、密钥密码、目标接口地址需替换为实际值。
内容的提问来源于stack exchange,提问作者StormBreaker
相关产品推荐
相关产品推荐

