SpringBoot 开启HTTPS
获取SSL证书
正常情况下,证书都是CA机构颁发的,但个人也可以通过借助工具生成SSL证书,例如,JDK自带的keytool和openssl,这种证书不会被浏览器信任,但加密功能够正常使用的。
keytool路径$JAVA_HOME/bin/keytool
获取服务端证书
keytool -genkey -alias server -keyalg RSA -keypass 123456 -keystore /e/key/server.p12 -storetype PKCS12 -storepass 123456 -validity 3650 -dname "CN=localhost" -ext SAN=ip:127.0.0.1,dns:localhost
生成的server.p12文件包含服务端私钥和证书相关信息
获取客户端证书
-
创建客户端PKCS文件,该文件包含客户端私钥和证书相关信息
$ keytool -genkey -alias client -keyalg RSA -keypass 123456 -keystore /e/key/client.p12 -storetype PKCS12 -storepass 123456 -validity 3650 -dname "CN=client"
-
导出客户端证书,要能够支持双向认证,需要将客户端证书导入到服务端信任库(服务端信任库:得到服务端信任的客户端列表)
因为不能直接将PKCS文件导入到信任库,所以要先通过PKCS文件(.p12)导出为证书文件(.cer)
keytool -export -alias client -keystore /e/key/client.p12 -storepass 123456 -file /e/key/client.cer -rfc
将客户端导入到服务端信任列表
$ keytool -import -alias clientCert -keystore /e/key/truststore.jks -storepass 123456 -file /e/key/client.cer
最终得到的文件
- client.p12
- server.p12
- client.cer
- truststore.jks
SpringBoot配置
server:
port: 8080 #HTTPS协议默认端口号为443,需要使用其他端口时,您可以在此处自定义。
ssl:
enable: true, # 是否开启
client-auth: need # 是否验证客户端。默认want-不强制验证;need-需要验证;none-不验证。
key-alias: server # 服务端证书别名
key-store-password: 123456 # 证书密码
key-store-type: PKCS12 # 证书类型
key-store: classpath:server.p12 # 路径
trust-store-password: 123456 # 信任库密码
trust-store: classpath:truststore.jks # 信任库
客户端安装证书
因为服务端需要验证客户端,所以客户端需要安装证书。
以chrome为例,chrome版本 113.0.5672.93
**settings->Privacy And Security->Security->Manage device certificates->**导入
点击“下一步”
浏览,选择client.p12,下一步输入密码,一直点击到完成即可。
验证
服务端验证接口
@GetMapping("test-https")
public Map<String, String> test() {
Map<String, String> map = new HashMap<>();
map.put("test result", "请求成功");
return map;
}
浏览器访问https://localhost:8080/test-https
浏览器弹出证书选择框,选择刚才导入证书
请求成功
如果浏览器不导入client.p12,访问时会报错ERR_BAD_SSL_CLIENT_AUTH_CERT
HTTP转HTTPS
直接发起HTTP请求
添加配置
@Configuration
public class HttpConfig {
@Bean
public Connector connector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme("http");
connector.setPort(8081);
connector.setSecure(false);
// 将8081转到8080
connector.setRedirectPort(8080);
return connector;
}
@Bean
public TomcatServletWebServerFactory tomcatServletWebServerFactory(Connector connector) {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
@Override
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint("CONFIDENTIAL");
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/*");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
};
tomcat.addAdditionalTomcatConnectors(connector);
return tomcat;
}
}
重启服务,修改服务端口再次发起HTTP请求http://localhost:8081/test-https
请求重定向到8080