一、生成证书
03-OpenSSL-创建带SAN扩展的证书并进行CA自签 或者参考 02-HTTPS证书生成、验签 、证书链 注意这里的证书生成需要带SAN
二、SpringBoot单向认证
修改yml文件
server:
port: 8088
ssl:
key-alias: server
key-store: classpath:server.p12
key-store-password: huawei
key-store-type: PKCS12
curl带自签名CA证书访问:关于curl命令进行https访问可以查看:
curl -v -I --cacert ca.crt https://www.huanghe.com:8088/api/test
curl也可以忽略证书访问
curl -v -I https://www.huanghe.com:8088/api/test -k
三、SpringBoot双向认证
理论上一共需要准备四个文件,两个keystore文件和两个truststore文件。 通信双方分别拥有一个keystore和一个truststore,keystore用于存放自己的密钥和公钥,truststore用于存放所有需要信任方的公钥。
keytool -genkeypair -keyalg RSA -keysize 2048 -alias server -dname "CN=huanghe,OU=huawei,O=huawei,C=CN" -ext "SAN:c=DNS:localhost,IP:127.0.0.1" -validity 3650 -keystore server.jks -storepass huawei -keypass huawei -deststoretype pkcs12
CN=huanghe,OU=huawei,O=huawei,C=CN"正确吗? CN:您的名字与姓氏是什么 huanghe OU :您的组织单位名称是什么 huawei O:您的组织名称是什么? huawei C:该单位的两字母国家代码是什么 CN
keytool -genkeypair -keyalg RSA -keysize 2048 -alias client -dname "CN=huanghe,OU=huawei,O=huawei,C=CN" -ext "SAN:c=DNS:localhost,IP:127.0.0.1" -validity 3650 -keystore client.jks -storepass huawei -keypass huawei -deststoretype pkcs12
keytool -export -alias server -keystore server.jks -storepass huawei -file server.cer
keytool -export -alias client -keystore client.jks -storepass huawei -file client.cer
keytool -import -alias client -keystore servertrust.jks -storepass huawei -file client.cer
keytool -import -alias server -keystore clienttrust.jks -storepass huawei -file server.cer
- 这里简单的记录一下:为什么在生成
.jks
文件的时候,需要加上SAN
。 因为不加入SAN
会出现报错:Certificate for doesn't match any of the subject alternative names。回答请看这
单项认证是客户端校验服务端,双向认证则服务端同时要校验客户端。双向认证具体实现:
- 在服务端增加如下配置,表示服务端开启客户端校验
# 开启双向认证(客户端与服务端互相校验)
server:
port: 8088
ssl:
key-alias: server
key-store: classpath:double/server.jks
key-store-password: huawei
key-store-type: JKS
trust-store: classpath:double/servertrust.jks
trust-store-password: huawei
trust-store-type: JKS
client-auth: need
启动代码:
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
try {
getHKVesselTrip();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void getHKVesselTrip() throws Exception {
// 客户端证书类型
KeyStore clientStore = KeyStore.getInstance("JKS");
// 加载客户端证书,即自己的私钥
clientStore.load(getClassLoader().getResourceAsStream("double/client.jks"), "huawei".toCharArray());
// 创建密钥管理工厂实例
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
// 初始化客户端密钥库
kmf.init(clientStore, "huawei".toCharArray());
KeyManager[] kms = kmf.getKeyManagers();
// 创建信任库管理工厂实例
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
// 信任库类型
KeyStore trustStore = KeyStore.getInstance("JKS");
// 加载信任库,即服务端公钥
trustStore.load(getClassLoader().getResourceAsStream("double/clienttrust.jks"), "huawei".toCharArray());
// 初始化信任库
tmf.init(trustStore);
TrustManager[] tms = tmf.getTrustManagers();
// 建立TLS连接
SSLContext sslContext = SSLContext.getInstance("TLS");
// 初始化SSLContext
sslContext.init(kms, tms, new SecureRandom());
SSLConnectionSocketFactory sslsf =
new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
try {
HttpGet httpget = new HttpGet("https://127.0.0.1:8088/api/test");
System.out.println("executing request" + httpget.getRequestLine());
CloseableHttpResponse response = httpclient.execute(httpget);
try {
HttpEntity entity = response.getEntity();
if (entity != null) {
System.out.println(EntityUtils.toString(entity));
}
} finally {
response.close();
}
} finally {
httpclient.close();
}
}
}
运行结果:
更多内容关注微信公众号 ”前后端技术精选“,或者语雀,里面有更多知识:www.yuque.com/riverzmm/uu… 《安全》