java-https客户端双向认证SSL
springboot下https双向认证开发经验
·
项目场景:
springboot 项目作为客户端请求服务端接口,为了保证请求安全,需要采用https双向认证.使用OkHttpClient加载证书
问题描述
双向认证过程,作为客户端除了需要从服务器端下载服务器的公钥证书进行验证外,还需要把客户端的公钥证书上传到服务器端给服务器端进行验证,等双方都认证成功,开始数据传输.
现客户端有服务器根证书:root.cer
客户端证书:client.pfx
实现步骤:
- 登录有openssl工具的服务器(一般Linux系统默认都有此工具)
- 利用证书格式转换命令cer转pem格式
openssl x509 -inform der -in root.cer -out root.pem
- 添加根证书(root.pem)至可信任证书库(指客户端服务器)
3.1 进入证书库:cd /Library/Java/JavaVirtualMachines/jdk1.8.0_301.jdk/Contents/Home/jre/lib/security/
(实际服务器的jvm路径)
3.2执行导入命令:keytool -import -alias ca -keystore cacerts -file /root/root.pem
- 将客户端证书《client.pfx》转成keystore,用程序访问服务地址:
https://serverip:port/(用实际的服务器IP、端口替换serverip和port,确认能够访问的预期内容)
4.1keytool -importkeystore -srckeystore client.pfx -destkeystore client.jks -srcstoretype PKCS12 -deststoretype JKS
4.2keytool -importkeystore -srckeystore client.jks -srcstoretype JKS -deststoretype PKCS12 -destkeystore client.keystore
- 将client.keystore 加载至java代码,代码如下:
java代码 springboot OkHttpClient加载过程
将client.keystore 放在classpath下
private SSLSocketFactory createSSLSocketFactory(TrustManager[] trustAllCerts) {
SSLSocketFactory ssfFactory = null;
try {
// 加载客户端证书
KeyStore keyStore = KeyStore.getInstance("PKCS12");
ClassPathResource resource = new ClassPathResource("ssl/client.keystore");
InputStream keyStoreInputStream = resource.getInputStream();
keyStore.load(keyStoreInputStream, "YourPassword".toCharArray());
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
keyManagerFactory.init(keyStore, "YourPassword".toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("SunX509");
trustManagerFactory.init(keyStore);
//服务端
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(keyManagerFactory.getKeyManagers(), trustAllCerts, new SecureRandom());
ssfFactory = sslContext.getSocketFactory();
} catch (Exception e) {
e.printStackTrace();
}
return ssfFactory;
}
okHttpClient = new OkHttpClient.Builder()
.connectTimeout(60, TimeUnit.SECONDS)//连接超时 设置
.writeTimeout(60, TimeUnit.SECONDS)//写超时
.readTimeout(60, TimeUnit.SECONDS)//读超时
.sslSocketFactory(createSSLSocketFactory(trustManagers), (X509TrustManager) trustManagers[0]) //支持 ssl证书
.hostnameVerifier((hostName, session) -> true) //设置用于确认响应证书适用于 HTTPS 连接请求的主机名的验证程序
.retryOnConnectionFailure(true) //连接失败时重试
.addInterceptor(logInterceptor) // 添加http日日拦截打印
.build();
private static TrustManager[] buildTrustManagers() {
return new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
}
};
}
证书加载完成,正常调用即可.
补充Spring Boot应用程序中加载资源文件的几种常见方式:
1通过ResourceLoader加载类路径下的资源文件:
@Autowired
private ResourceLoader resourceLoader;
public void loadClasspathResource() {
Resource resource = resourceLoader.getResource("classpath:ssl/client.keystore");
// 使用Resource对象读取资源文件内容
}
2.通过ClassPathResource加载类路径下的资源文件:
ClassPathResource resource = new ClassPathResource("ssl/client.keystore");
更多推荐
所有评论(0)