1. 程式人生 > >SpringBoot配置SSL

SpringBoot配置SSL

一、概念

1、為什麼要使用證書
        對資料進行簽名(加密)是我們在網路中最常見的安全操作。簽名有雙重作用,作用一就是保證資料的完整性,證明資料並非偽造,而且在傳輸的過程中沒有被篡改,作用二就是防止資料的釋出者否認其釋出了該資料。
        簽名同時使用了非對稱性加密演算法和訊息摘要演算法,對一塊資料簽名時,會先對這塊資料進行訊息摘要運算生成一個摘要,然後對該摘要使用釋出者的私鑰進行加密。 比如微信公眾平臺開發中最常見的呼叫api介面方法是將引數進行字典序排序,然後將引數名和引數值接成一個字串,組合的字串也就相當於我們這裡說的摘要,然後將摘要用平臺金鑰加密。
        接收者(客戶端)接受到資料後,先使用釋出者的公鑰進行解密得到原資料的摘要,再對接收到的資料計算摘要,如果兩個摘要相同,則說明資料沒有被篡改。同時,因為釋出者的私鑰是不公開的,只要接收者通過釋出者的公鑰能成功對資料進行解密,就說明該資料一定來源於該釋出者。
        那麼怎麼確定某公鑰一定是屬於某釋出者的呢?這就需要證書了。證書由權威認證機構頒發,其內容包含證書所有者的標識和它的公鑰,並由權威認證機構使用它的私鑰進行簽名。資訊的釋出者通過在網路上釋出證書來公開它的公鑰,該證書由權威認證機構進行簽名,認證機構也是通過釋出它的證書來公開該機構的公鑰,認證機構的證書由更權威的認證機構進行簽名,這樣就形成了證書鏈。證書鏈最頂端的證書稱為根證書,根證書就只有自簽名了。總之,要對網路上傳播的內容進行簽名和認證,就一定會用到證書。關於證書遵循的標準,最流行的是 X.509

2、SSL協議
        SSL(Secure Socket Layer,安全套接層):是為網路通訊提供安全及資料完整性的一種安全協議。SSL位於TCP/IP協議與各種應用層協議之間,為資料通訊提供安全支援。SSL協議分為兩層:1)SSL記錄協議,建立在可靠的傳輸協議(如TCP)之上,為高層協議提供資料封裝、壓縮、加密等基本功能的支援;2)SSL握手協議,建立在SSL記錄協議之上,用於在實際資料傳輸開始前,通訊雙方進行身份認證、協商加密演算法、交換加密金鑰等。

二、SpringBoot配置SSL

1、生成證書

keytool -genkey -alias tomcat -keyalg RSA -keystore /Users/zhanghao/Desktop/tomcatkeystore.keystore  -dname "CN=localhost, OU=localhost, O=localhost, L=SH, ST=SH, C=CN" -keypass 123qwe

引數說明:
-genkey:表示要建立一個新的金鑰
-alias:和keystore關聯的別名,這個alias通常不區分大小寫,預設“mykey”
-keyalg:使用加密的演算法,這裡是RSA,預設“DSA”
-keystore:金鑰儲存的檔案位置,預設“使用者宿主目錄中名為 .keystore 的檔案,沒有不會新建,所以還是指定的好”
-dname:表明了金鑰的發行者身份
  CN=commonName 注:生成證書時,CN要和伺服器的域名相同,如果在本地測試,則使用localhost
  OU=organizationUnit
  O=organizationName
  L=localityName
  S=stateName
  C=country
-keypass:私有金鑰的密碼,這裡設定為“123qwe”
其他引數
-storepass :存取密碼(我用的mac jdk1.8.0_131 不支援這個引數)
-validity:金鑰的有效期,預設為90天(我用的mac jdk1.8.0_131 不支援這個引數)
-keysize 1024(沒用過)
-file 讀時為標準輸入,寫時為標準輸出 (沒用過)

注:cacerts證書檔案(The cacerts Certificates File),存在於$JAVA_HOME\jre\lib\security目錄下,是Java系統的CA證書倉庫

2、SpringBoot配置SSL
1)將證書檔案複製到專案的根目錄
2)配置檔案

server:
  port: 8080
  ssl:
    key-store: tomcatkeystore.keystore
    key-store-password: 123qwe
    key-store-type: JKS
    key-alias: tomcat

http訪問
在這裡插入圖片描述
https訪問
在這裡插入圖片描述

3、配置http自動轉向https
1)埠配置

http:
  port: 8080
server:
  port: 8443

2)埠監聽轉換

import org.apache.catalina.Context;
import org.apache.catalina.connector.Connector;
import org.apache.tomcat.util.descriptor.web.SecurityCollection;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class HttpsConfig {

    @Value("${http.port}")
    private int httpPort;

    @Value("${server.port}")
    private int serverPort;

    @Bean
    public TomcatServletWebServerFactory servletContainer() {
        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(httpConnector());
        return tomcat;
    }

    @Bean
    public Connector httpConnector() {
        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
        connector.setScheme("http");
        connector.setPort(httpPort);
        connector.setSecure(false);
        connector.setRedirectPort(serverPort);
        return connector;
    }

}

請求http://localhost:8080則自動重定向到https://localhost:8443