首頁>技術>

要讓專案實現 ssl 免密登入,首先需要開啟 https

所以先從 Spring Boot 如何開啟 https 說起。

建立服務端證書

為了開啟 https ,我們需要一份證書。

實際開發中,會在網上申請一個機構頒發的證書。這裡為了方便,我會使用 openssl 命令自己生成一個證書來使用。

openssl req -x509 -sha256 -days 3650 -newkey rsa:4096 -keyout rootCA.key -out rootCA.crt

所有的密碼都是 123456 ,然後根據提示輸入相關資訊就好,如果嫌麻煩也可以直接回車跳過。

這樣我們就得到了證書 rootCA.crt 和私鑰 rootCA.key

要在 Spring Boot 中實現伺服器端 X.509 身份驗證,還需要給我們的服務端也生成一個證書。

openssl req -new -newkey rsa:4096 -keyout localhost.key -out localhost.csr

同樣,密碼是 123456 ,檔名 localhost 可以自行修改。

接下來就是用 rootCA 給我們的服務端證書做簽名了,在此之前,我們先寫一個配置檔案,裡面寫有一些基本的配置

vi conf.config
authorityKeyIdentifier=keyid,issuerbasicConstraints=CA:FALSEsubjectAltName = @alt_names[alt_names]DNS.1 = localhost

其中 DNS.1 的值就是你的域名,比如 www.segmentfault.comlocalhost 等等。如果這裡填錯了,訪問網站時,瀏覽器會提示網站不安全。

然後給服務端證書籤名,會提示你輸入 rootCA 的密碼

openssl x509 -req -CA rootCA.crt -CAkey rootCA.key -in localhost.csr -out localhost.crt -days 365 -CAcreateserial -extfile conf.config

成功後,讓我們檢視一下證書的資訊

openssl x509 -in localhost.crt -text

最後再將簽名證書和私鑰打包到 PKCS 檔案中

openssl pkcs12 -export -out localhost.p12 -name "localhost" -inkey localhost.key -in localhost.crt

這條指令會要你先輸入 localhost.key 的密碼,然後再要你定義 localhost.p12 的密碼。 localhost.p12 這個密碼一定要記住,因為在 Spring 的配置檔案中有用到。

另外需要特別注意的是, Spring 配置檔案中 server.ssl.keyAlias 的值,就是命令中的 localhost(-name "localhost")

Spring Boot開啟https

localhost.p12 複製到 resources 目錄下之後編譯專案

修改application.properties檔案
server.port=8888server.ssl.key-store=classpath:localhost.p12server.ssl.key-store-password=123456server.ssl.keyStoreType=PKCS12server.ssl.keyAlias=localhost

chrome://settings/security 中,選擇 受信任的根證書頒發機構 匯入 rootCA.crt

這時啟動專案,就可以使用 https 訪問網站了,而且瀏覽器提示網站時安全的。

建立信託證書

信託證書中會存有 信任的外部實體的證書

這裡我們只要將 rootCA.crt 新增進去就可以了

keytool -import -trustcacerts -noprompt -alias ca -ext san=dns:localhost,ip:127.0.0.1 -file rootCA.crt -keystore localhost.jks

然後將 localhost.jks 新增到專案中,並修改配置檔案

application.properties新增:
server.ssl.trust-store=classpath:localhost.jksserver.ssl.trust-store-password=123456server.ssl.client-auth=need
注意:此時由於添加了server.ssl.client-auth=need,因為沒有添加個人證書,所以這個時候重新整理頁面,專案會無法訪問,如果想要同時兼任普通登入,可以將need改成want,但是want只會在第一次訪問頁面時才會向客戶索取個人證書建立客戶端證書

現在建立一個客戶端的證書,步驟和服務端的差不多一樣。

openssl req -new -newkey rsa:4096 -nodes -keyout shurlormes.key -out shurlormes.csr

在生成客戶端證書時,那些資訊不建議跳過,因為在後續的步驟中,會獲取其中的資訊用以登入。比如我在 Common Name 處填寫的資訊,就是等下用來登入的使用者名稱。

接下來用 RootCA 給客戶端證書籤名

openssl x509 -req -CA rootCA.crt -CAkey rootCA.key -in shurlormes.csr -out shurlormes.crt -days 365 -CAcreateserial

然後再將簽名證書和私鑰打包到 PKCS 檔案中

openssl pkcs12 -export -out shurlormes.p12 -name "shurlormes" -inkey shurlormes.key -in shurlormes.crt

最後在 chrome://settings/security 選擇 個人證書shurlormes.p12 匯入,期間會要你輸入它的密碼。

這時候重新整理頁面,瀏覽器就會彈出一個對話方塊,讓你選擇個人認證了。

Spring Boot獲取個人證書資訊

恭喜你,到了這一步, pki 登入已經完成了 99% 了。接下來就是透過 request 獲取證書資訊,然後處理字串,拿到使用者名稱做登入即可。

@RequestMapping("/login")public String login(HttpServletRequest request) {    X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");    if(certs != null) {        X509Certificate gaX509Cert = certs[0];        String dn = gaX509Cert.getSubjectDN().toString();        System.out.println("個人證書資訊:" + dn);        String username = "";        String[] dnArray = dn.split(",");        for (String dnItem : dnArray) {            String[] dnInfo = dnItem.split("=");            String key = dnInfo[0];            String value = dnInfo[1];            if("cn".equalsIgnoreCase(key.trim())) {                username = value;                break;            }        }        System.out.println("使用者名稱:" + username);        if(!StringUtils.isEmpty(username)) {            SecurityContext securityContext = SecurityContextHolder.getContext();            User userDetails = new User(username, "", Collections.EMPTY_LIST);            securityContext.setAuthentication(new UsernamePasswordAuthenticationToken(userDetails, "", Collections.EMPTY_LIST));            return "redirect:/";        }    }    return "login";}
Spring Boot 同時開啟http和https

相信大家都發現了,現在專案只能透過 https 訪問,如果用 http 訪問瀏覽器直接返回 Bad request 了。

要同時開啟 httpshttp ,只需新增一個 TomcatConfig 就可以

@Configurationpublic class TomcatHttpConfig {    @Bean    public TomcatServletWebServerFactory servletContainer() {        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();        tomcat.addAdditionalTomcatConnectors(initiateHttpConnector());        return tomcat;    }    private Connector initiateHttpConnector() {        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");        connector.setScheme("http");        connector.setPort(9999);        connector.setSecure(false);        return connector;    }}

這時候啟動專案,注意看控制檯列印的資訊。

說明已經成功啟動 http 在埠 9999https8888 ,頁面也可以成功訪問了。

Spring Boot http自動跳轉https

上面我們已經可以同時訪問 htt p和 https ,但如果我要訪問 http 的時候,自動跳轉的 https 呢?

只需要在上面的基礎上稍微改改就可以了。

@Configurationpublic class TomcatHttpConfig {    @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(initiateHttpConnector());        return tomcat;    }    private Connector initiateHttpConnector() {        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");        connector.setScheme("http");        connector.setPort(9999);        connector.setSecure(false);        connector.setRedirectPort(8888);        return connector;    }}
踩坑總結把服務端證書 p12 檔案新增到專案 resources 後,記得 rebuild 專案,否則 targetclasses 中沒有生成證書檔案,會導致專案啟動失敗。application.properties 中的 server.ssl.keyAlias 需要和生成 p12 檔案的 -name 一致,否則也會導致專案無法啟動。如果要指定域名,需要修改 conf.confg 中的 DNS.1 ,否則瀏覽器會提示網站不安全。

29
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 基於SpringBoot+Cloud微服務分散式架構實戰手冊