Spring MVC中使用双向SSL证书调用API的Java示例求助
双向SSL认证REST API调用Spring MVC实现示例
前置证书格式转换
Java原生KeyStore仅支持JKS/PKCS12格式的密钥库,你需要先把手中的证书文件转换为对应格式:
- 生成服务端信任库truststore:将服务端公共证书
public.cer导入信任库,用于后续校验服务端身份
执行命令:
执行过程中按提示设置信任库密码即可keytool -import -alias server-public-cert -file public.cer -keystore truststore.jks -storetype JKS - 生成客户端密钥库keystore:将客户端私有证书
sslclient.private转为PKCS12格式密钥库,private.passphrase中存储的是客户端私钥的解锁口令,转换时需要用到
执行命令:
若你没有单独的客户端公钥证书openssl pkcs12 -export -inkey sslclient.private -in sslclient.crt -name client-auth-cert -out client-keystore.p12 -passin file:private.passphrasesslclient.crt,可确认sslclient.private是否包含完整证书链,直接替换上述命令的输入文件路径即可
依赖引入(Maven示例)
你需要引入Apache HttpClient依赖用于构建支持SSL的请求客户端,Spring MVC项目默认已包含spring-web依赖无需额外引入:
<dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.14</version> </dependency>
RestTemplate SSL配置类实现
我们通过配置类自定义支持双向SSL的RestTemplate实例,后续直接注入该实例即可调用双向认证接口:
import org.apache.http.ssl.SSLContextBuilder; 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.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; import javax.net.ssl.SSLContext; import java.io.FileInputStream; import java.nio.file.Files; import java.nio.file.Paths; import java.security.KeyStore; @Configuration public class SslRestTemplateConfig { // 可将以下配置项放到application.properties中通过@Value注入,避免硬编码 private static final String KEYSTORE_PATH = "你的client-keystore.p12文件路径"; private static final String TRUSTSTORE_PATH = "你的truststore.jks文件路径"; private static final String PASSPHRASE_FILE_PATH = "你的private.passphrase文件路径"; private static final String TRUSTSTORE_PASSWORD = "你生成truststore时设置的密码"; @Bean public RestTemplate sslRestTemplate() throws Exception { // 读取私钥口令 String clientKeyPass = Files.readAllLines(Paths.get(PASSPHRASE_FILE_PATH)).get(0).trim(); // 加载客户端密钥库 KeyStore keyStore = KeyStore.getInstance("PKCS12"); try (FileInputStream keystoreIs = new FileInputStream(KEYSTORE_PATH)) { keyStore.load(keystoreIs, clientKeyPass.toCharArray()); } // 加载服务端信任库 KeyStore trustStore = KeyStore.getInstance("JKS"); try (FileInputStream truststoreIs = new FileInputStream(TRUSTSTORE_PATH)) { trustStore.load(truststoreIs, TRUSTSTORE_PASSWORD.toCharArray()); } // 构建SSL上下文 SSLContext sslContext = SSLContextBuilder.create() .loadKeyMaterial(keyStore, clientKeyPass.toCharArray()) .loadTrustMaterial(trustStore, null) .build(); // 构建支持SSL的HttpClient CloseableHttpClient httpClient = HttpClients.custom() .setSSLContext(sslContext) .build(); // 生成RestTemplate实例 HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); requestFactory.setHttpClient(httpClient); // 可选配置超时时间 requestFactory.setConnectTimeout(5000); requestFactory.setReadTimeout(10000); return new RestTemplate(requestFactory); } }
接口调用示例
直接注入上述配置好的sslRestTemplate即可发起双向SSL认证的接口请求,和普通RestTemplate用法完全一致:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; @RestController public class TestController { @Autowired private RestTemplate sslRestTemplate; @GetMapping("/test-ssl-api") public String testTwoWaySslApi() { String targetApiUrl = "双向认证接口的目标地址"; // 调用GET接口示例 return sslRestTemplate.getForObject(targetApiUrl, String.class); } }
注意事项
- 生产环境不要把证书密码、文件路径硬编码到代码中,建议放到配置中心或加密配置文件中
- 证书文件建议放到项目
resources目录下,通过ResourceUtils.getFile("classpath:xxx.jks")方式加载,避免绝对路径适配问题 - 如果调用接口出现证书校验错误,可先确认导入到truststore中的
public.cer是否是目标服务端的根证书或站点证书
内容的提问来源于stack exchange,提问作者Itok
相关产品推荐
相关产品推荐

