Spring Boot文档阅读笔记-how-to-implement-2-way-ssl-using-spring-boot
Posted IT1995
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Boot文档阅读笔记-how-to-implement-2-way-ssl-using-spring-boot相关的知识,希望对你有一定的参考价值。
two-way-ssl需要12次握手(除去TCP的三次握手),如下图:
双向认证过程:
1.客户端发送ClientHello消息,告诉服务端要使用SSL。
2.客户端发送ServerHello的响应,告诉客户端使用SSL。
3.服务端发送证书给客户端;
4.服务端发送发送数据,要求客户端发送证书;
5.此时客户端与服务端招呼已经结束;
6.客户端发送自己的证书给服务端(客户端认证服务端证书成功);
7.客户端发送session key(使用服务端公钥加密);
8.客户端发送一个CertificateVerify消息让服务器知道它拥有发送证书;
9.客户端发送自己支持的通道加密套给服务端;
10.客户端要服务端从中选着一个;
11.服务端选择一个加密套,并且告诉客户端,我选择了这个;
12.服务端发送认证完成。
使用keytool生成证书:
keytool -genkeypair -alias client-app -keyalg RSA -keysize 2048 -storetype JKS -keystore client-app.jks -validity 3650 -ext SAN=dns:localhost,ip:127.0.0.1
keytool -genkeypair -alias server-app -keyalg RSA -keysize 2048 -storetype JKS -keystore server-app.jks -validity 3650 -ext SAN=dns:localhost,ip:127.0.0.1
keytool -export -alias client-app -file client-app.crt -keystore client-app.jks
keytool -export -alias server-app -file server-app.crt -keystore server-app.jks
keytool -import -alias server-app -file server-app.crt -keystore client-app.jks
keytool -import -alias client-app -file client-app.crt -keystore server-app.jks
下面使用Spring Boot进行SSL双向认证
程序结构如下:
关键代码:
服务端
application.properties
spring.application.name=server-app
server.port=9002
server.ssl.enabled=true
server.ssl.client-auth=need
server.ssl.key-store=classpath:server-app.jks
server.ssl.key-store-password=server-app
server.ssl.key-alias=server-app
server.ssl.key-store-type=JKS
server.ssl.key-store-provider=SUN
server.ssl.trust-store=classpath:server-app.jks
server.ssl.trust-store-password=server-app
server.ssl.trust-store-type=JKS
Controller.java
package cn.server;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/server-app")
public class Controller {
@GetMapping("/data")
public String getData(){
System.out.println("Returning data from server-app data method");
return "Hello from Server-App-data method";
}
}
客户端
application.properties
spring.application.name=client-app
server.port=9001
server.ssl.enabled=true
server.ssl.client-auth=need
server.ssl.key-store=classpath:client-app.jks
server.ssl.key-store-password=client-app
server.ssl.key-alias=client-app
server.ssl.key-store-type=JKS
server.ssl.key-store-provider=SUN
server.ssl.trust-store=classpath:client-app.jks
server.ssl.trust-store-password=client-app
server.ssl.trust-store-type=JKS
endpoint.server-app=https://localhost:9002/server-app/data
ClientMain.java
package cn.client;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import java.io.InputStream;
import java.net.URI;
import java.security.KeyStore;
@SpringBootApplication
public class ClientMain implements CommandLineRunner {
@Autowired
RestTemplate restTemplate;
@Value("${endpoint.server-app}")
private String msEndpoint;
@Bean
public RestTemplate getRestTemplate(){
RestTemplate restTemplate = new RestTemplate();
KeyStore keyStore;
HttpComponentsClientHttpRequestFactory requestFactory = null;
try {
keyStore = KeyStore.getInstance("jks");
ClassPathResource classPathResource = new ClassPathResource("client-app.jks");
InputStream inputStream = classPathResource.getInputStream();
keyStore.load(inputStream, "client-app".toCharArray());
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(new SSLContextBuilder()
.loadTrustMaterial(null, new TrustSelfSignedStrategy())
.loadKeyMaterial(keyStore, "client-app".toCharArray()).build(),
NoopHostnameVerifier.INSTANCE);
HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(socketFactory)
.setMaxConnTotal(Integer.valueOf(5))
.setMaxConnPerRoute(Integer.valueOf(5))
.build();
requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
requestFactory.setReadTimeout(Integer.valueOf(10000));
requestFactory.setConnectTimeout(Integer.valueOf(10000));
restTemplate.setRequestFactory(requestFactory);
}
catch (Exception exception) {
System.out.println("Exception Occured while creating restTemplate "+exception);
exception.printStackTrace();
}
return restTemplate;
}
public static void main(String[] args) {
SpringApplication.run(ClientMain.class, args);
}
@Override
public void run(String... args) throws Exception {
String forObject = restTemplate.getForObject(new URI(msEndpoint), String.class);
System.out.println(forObject);
}
}
源码打包下载地址:
https://github.com/fengfanchen/Java/tree/master/SpringBoot-two-way-ssl
以上是关于Spring Boot文档阅读笔记-how-to-implement-2-way-ssl-using-spring-boot的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot文档阅读笔记-Scheduling Tasks
Spring Boot文档阅读笔记-exception handling–@ExceptionHandler解析与实例
Spring Boot文档阅读笔记-CORS Support
Spring Boot文档阅读笔记-CORS Support
Spring Boot文档阅读笔记-CORS Support
Spring Boot文档阅读笔记-how-to-implement-2-way-ssl-using-spring-boot