SpringBoot添加SSL證書,開啟HTTPS方式(單向認證服務端)
一、前言
通過HTTP協(xié)議傳輸數(shù)據(jù),并不會對數(shù)據(jù)進行加密,所以存在著一定的風險,容易被抓包破解數(shù)據(jù),而且現(xiàn)在各種瀏覽器對使用HTTP協(xié)議的網(wǎng)站也會提示不安全。
通過將HTTP協(xié)議升級為HTTPS協(xié)議可以提高安全系數(shù)。使用HTTPS協(xié)議就需要了解一下SSL協(xié)議。
SSL(Secure Sockets Layer 安全套接字協(xié)議),及其繼任者傳輸層安全(Transport Layer Security,TLS)是為網(wǎng)絡通信提供安全及數(shù)據(jù)完整性的一種安全協(xié)議。
TLS與SSL在傳輸層與應用層之間對網(wǎng)絡連接進行加密。
SSL協(xié)議位于TCP/IP協(xié)議與各種應用層協(xié)議之間,為數(shù)據(jù)通訊提供安全支持。
SSL協(xié)議可分為兩層:
- SSL記錄協(xié)議(SSL Record Protocol):它建立在可靠的傳輸協(xié)議(如TCP)之上,為高層協(xié)議提供數(shù)據(jù)封裝、壓縮、加密等基本功能的支持。
- SSL握手協(xié)議(SSL Handshake Protocol):它建立在SSL記錄協(xié)議之上,用于在實際的數(shù)據(jù)傳輸開始前,通訊雙方進行身份認證、協(xié)商加密算法、交換加密密鑰等。
服務器認證階段:
1)客戶端向服務器發(fā)送一個開始信息“Hello”以便開始一個新的會話連接;
2)服務器根據(jù)客戶的信息確定是否需要生成新的主密鑰,如需要則服務器在響應客戶的“Hello”信息時將包含生成主密鑰所需的信息;
3)客戶根據(jù)收到的服務器響應信息,產(chǎn)生一個主密鑰,并用服務器的公開密鑰加密后傳給服務器;
4)服務器恢復該主密鑰,并返回給客戶一個用主密鑰認證的信息,以此讓客戶認證服務器。
用戶認證階段:
- 在此之前,服務器已經(jīng)通過了客戶認證,這一階段主要完成對客戶的認證。
- 經(jīng)認證的服務器發(fā)送一個提問給客戶,客戶則返回(數(shù)字)簽名后的提問和其公開密鑰,從而向服務器提供認證。
SSL協(xié)議提供的安全通道有以下三個特性:
- 機密性:SSL協(xié)議使用密鑰加密通信數(shù)據(jù)。
- 可靠性:服務器和客戶都會被認證,客戶的認證是可選的。
- 完整性:SSL協(xié)議會對傳送的數(shù)據(jù)進行完整性檢查。
從SSL 協(xié)議所提供的服務及其工作流程可以看出,SSL協(xié)議運行的基礎是商家對消費者信息保密的承諾,這就有利于商家而不利于消費者。
在電子商務初級階段,由于運作電子商務的企業(yè)大多是信譽較高的大公司,因此這問題還沒有充分暴露出來。
但隨著電子商務的發(fā)展,各中小型公司也參與進來,這樣在電子支付過程中的單一認證問題就越來越突出。
雖然在SSL3.0中通過數(shù)字簽名和數(shù)字證書可實現(xiàn)瀏覽器和Web服務器雙方的身份驗證,但是SSL協(xié)議仍存在一些問題,比如,只能提供交易中客戶與服務器間的雙方認證,在涉及多方的電子交易中,SSL協(xié)議并不能協(xié)調(diào)各方間的安全傳輸和信任關系。
在這種情況下,Visa和 MasterCard兩大信用卡公司組織制定了SET協(xié)議,為網(wǎng)上信用卡支付提供了全球性的標準。
以上摘自百度。
二、SpringBoot中配置SSL(單向)
SSL證書的頒發(fā)必須是公開公認的CA機構(gòu)頒發(fā)的,在瀏覽器中才會被認可是合法的;
SSL證書是針對域名的,單域名的SSL證書對非該域名也是無效的通配域名證書對一級域名和二級域名都有效。
例如:你有一個域名為 abc.com的一級域名,解析了一個.abc.com的二級域名和 b.abc.com的二級域名。當你為a.abc.com申請的單域名證書對b.abc.com域名是無效的。
(PS:我看了網(wǎng)上很多通過keytool生成證書的,通過keytool生成的證書是自簽證書,不被瀏覽器鎖認可)
1、環(huán)境
spring boot 2.2.2
maven
一個域名(各大域名商有售,阿里、騰訊、華為)
SSL證書(阿里云上有免費的SSL證書,有效期一年)
2、客戶端單向認證服務端代碼實戰(zhàn)-JKS格式的證書
tomcat中支持JKS格式與PFX兩種格式的證書,下面先進行JKS格式的證書演示。
(1)準備一個JKS后綴的SSL證書。(域名.jks)
(2)快速構(gòu)建一個springboot模塊
(3) 在resources下新建一個ssl目錄,復制SSL證書到該目錄下
(4)在項目配置文件application.yml中配置SSL
server: port: 8090 #端口配置 ssl: #ssl配置 enabled: true # 默認為true #key-alias: alias-key # 別名(可以不進行配置) # 保存SSL證書的秘鑰庫的路徑 key-store: classpath:ssl/service.一級域名.jks key-password: 私鑰密碼 #key-store-password: 證書密碼 key-store-type: JKS 證書類型
上述配置中 key-password 是私鑰密碼
key-store-password 是證書密碼。
如果這兩個密碼相同的只配置一個即可,因為tomcat默認先用keyStore的pass去解私鑰。(PS:如果你使用阿里云上的免費SSL證書,下載jks格式的證書的時候,只有一個密碼,是證書的密碼)
(5)添加一個controller,測試是否生效
@RestController public class TestController { @RequestMapping(value = {"","/"}) public String testHttps(){ return "you success by https"; } }
(6)本地訪問 https://127.0.0.1:8090/
因為該證書對應的域名解析的服務器地址與現(xiàn)在訪問的地址不同,所以瀏覽器會提示訪問不安全,點擊【高級】后的【繼續(xù)前往…】繼續(xù)跳轉(zhuǎn),發(fā)現(xiàn)會有很明顯的不安全提示。
(7)打包,放到域名解析對應的服務器上進行測試,訪問:
https://域名:8090/
可以看到當部署到域名解析對應的服務器上時,通過瀏覽器訪問,瀏覽器出現(xiàn)一個小鎖的標識。
(8)本地使用http訪問: http://127.0.0.1:8090/
服務器http訪問:http://域名:8090/
通過上述訪問發(fā)現(xiàn),如果通過http訪問會提示訪問需要組合TLS,但是如果用戶直接通過這種方式訪問的話,存在著極差的用戶體驗。
3、HTTP 轉(zhuǎn)HTTPS
當用戶使用http訪問的時候,將http協(xié)議重定向到https端口
(1)修改配置文件
custom: # 自定義http啟動端口 http-port: 8089 配置 server: port: 8090 #端口配置 ssl: #ssl配置 enabled: true # 默認為true #key-alias: alias-key # 別名(可以不進行配置) # 保存SSL證書的秘鑰庫的路徑 key-store: classpath:ssl/service.一級域名.jks key-password: 私鑰密碼 #key-store-password: 證書密碼 key-store-type: JKS
(2)添加配置類
package cn.zlc.servicehttps.config; 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; /** * https配置,將http請求全部轉(zhuǎn)發(fā)到https * @author Jacob */ @Configuration public class HttpsConfig { @Value("${custom.http-port: 8080}") private Integer httpPort; @Value("${server.port}") private Integer port; @Bean public TomcatServletWebServerFactory servletContainer() { // 將http請求轉(zhuǎn)換為https請求 TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() { @Override protected void postProcessContext(Context context) { SecurityConstraint constraint = new SecurityConstraint(); // 默認為NONE constraint.setUserConstraint("CONFIDENTIAL"); SecurityCollection collection = new SecurityCollection(); // 所有的東西都https collection.addPattern("/*"); constraint.addCollection(collection); context.addConstraint(constraint); } }; tomcat.addAdditionalTomcatConnectors(httpConnector()); return tomcat; } /** * 強制將所有的http請求轉(zhuǎn)發(fā)到https * @return httpConnector */ @Bean public Connector httpConnector() { Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol"); connector.setScheme("http"); // connector監(jiān)聽的http端口號 connector.setPort(httpPort); connector.setSecure(false); // 監(jiān)聽到http的端口號后轉(zhuǎn)向到的https的端口號 connector.setRedirectPort(port); return connector; } }
(3)啟動成功后可以看見http啟動端口和https端口
(4)本地訪問http的8089端口 http://127.0.0.1:8089/
程序會將http端口的請求轉(zhuǎn)發(fā)到https端口,而用戶無需做操作。
本地直接訪問https端口和在服務器上直接訪問就不貼圖了。
4、同時開啟HTTP和HTTPS
如果我們不想強制所有的請求都重定向到https或者某些功能接口需要http的支持等等,我們也可以同時開啟http協(xié)議和https協(xié)議。
(1)修改配置類
package cn.zlc.servicehttps.config; 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; /** * https配置,將http請求全部轉(zhuǎn)發(fā)到https * @author Jacob */ @Configuration public class HttpsConfig { @Value("${custom.http-port: 8080}") private Integer httpPort; @Bean public TomcatServletWebServerFactory servletContainer() { TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory(); tomcat.addAdditionalTomcatConnectors(httpConnector()); return tomcat; } @Bean public Connector httpConnector() { Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol"); connector.setPort(httpPort); return connector; } }
(2)本地訪問http協(xié)議的8089端口:http://127.0.0.1:8089/
(3)本地訪問https的8090端口
通過對比發(fā)現(xiàn),如果我們通過http端口請求的話,不會自動重定向到https端口,而且也不會提示需要TLS端口請求。
而使用https請求的時候就會提示不安全(如果是放到服務器上訪問https就正常了);
5、客戶端單向認證服務端代碼實戰(zhàn)-PFX格式的證書
(1)配置文件如下:
custom: http-port: 8070 server: port: 8060 #端口配置 ssl: #ssl配置 enabled: true # 默認為true #key-alias: alias-key # 別名(可以不進行配置) # 保存SSL證書的秘鑰庫的路徑 key-store: classpath:ssl/5986342_一級域名.pfx #key-password: 私鑰密碼 pfx格式的使用key-password 無法正常啟動 key-store-type: PKCS12 #證書類型 key-store-password: 證書密碼
(2)不同點
主要的不同點就是key-store-type類型不同,同時如果是JKS的證書,使用私鑰密碼或者是證書密碼都行,但是pfx的證書如果只配置私鑰密碼無法正常啟動。
三、異常解決
使用jks格式的證書時,通過maven打包會出現(xiàn)證書內(nèi)容被修改,導致證書驗證失敗,出現(xiàn)Invalid keystore format sl證書格式不合法的異常,可在maven中添加一個插件
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>3.2.0</version> <configuration> <nonFilteredFileExtensions> <!--<nonFilteredFileExtension>p12</nonFilteredFileExtension>--> <nonFilteredFileExtension>jks</nonFilteredFileExtension> </nonFilteredFileExtensions> </configuration> </plugin>
其它解決方案,可查看我的另一篇博客:
異常:Invalid keystore format,spring boot配置ssl證書格式不合法解決
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
使用Spring初始化加載InitializingBean()方法
這篇文章主要介紹了使用Spring初始化加載InitializingBean()方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01Exception in thread main java.lang.NoClassDefFoundError錯誤解決方
這篇文章主要介紹了Exception in thread main java.lang.NoClassDefFoundError錯誤解決方法,需要的朋友可以參考下2016-08-08Spring mvc Controller和RestFul原理解析
這篇文章主要介紹了Spring mvc Controller和RestFul原理解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2020-03-03