SpringBoot 开启HTTPS

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文件包含服务端私钥和证书相关信息

获取客户端证书

  1. 创建客户端PKCS文件,该文件包含客户端私钥和证书相关信息

    $ keytool -genkey -alias client -keyalg RSA -keypass 123456 -keystore /e/key/client.p12 -storetype PKCS12 -storepass 123456 -validity 3650 -dname "CN=client"
    
  2. 导出客户端证书,要能够支持双向认证,需要将客户端证书导入到服务端信任库(服务端信任库:得到服务端信任的客户端列表)

    因为不能直接将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

1 个赞