11-HTTPS在SpringBoot中的配置

440 阅读2分钟

一、生成证书

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
 ​

image.png 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。回答请看这

单项认证是客户端校验服务端,双向认证则服务端同时要校验客户端。双向认证具体实现:

  1. 在服务端增加如下配置,表示服务端开启客户端校验
# 开启双向认证(客户端与服务端互相校验)
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();
            }
        }

    }

运行结果: image.png

更多内容关注微信公众号 ”前后端技术精选“,或者语雀,里面有更多知识:www.yuque.com/riverzmm/uu… 《安全》