如何輕松給Spring Boot配置文件加個(gè)密?
本文轉(zhuǎn)載自微信公眾號(hào)「程序新視界」,作者二師兄。轉(zhuǎn)載本文請(qǐng)聯(lián)系程序新視界公眾號(hào)。
在實(shí)踐中,項(xiàng)目的某些配置信息是需要進(jìn)行加密處理的,以減少敏感信息泄露的風(fēng)險(xiǎn)。比如,在使用Druid時(shí),就可以基于它提供的公私鑰加密方式對(duì)數(shù)據(jù)庫(kù)的密碼進(jìn)行加密。
但更多時(shí)候,比如Redis密碼、MQ密碼等敏感信息,也需要進(jìn)行加密,此時(shí)就沒(méi)那么方便了。本篇文章給大家介紹一款Java類(lèi)庫(kù)Jasypt,同時(shí)基于Spring Boot項(xiàng)目來(lái)演示一下如何對(duì)配置文件信息進(jìn)行加密。
一個(gè)簡(jiǎn)單的SpringBoot項(xiàng)目
我們先來(lái)創(chuàng)建一個(gè)簡(jiǎn)單的Spring Boot項(xiàng)目,構(gòu)建一個(gè)加密數(shù)據(jù)運(yùn)用的場(chǎng)景。
無(wú)論通過(guò)Idea或官網(wǎng)等方式,先創(chuàng)建一個(gè)Spring Boot項(xiàng)目,核心依賴為:
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
- <!-- 為了方便,通常會(huì)引入Lombok依賴 -->
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- </dependency>
創(chuàng)建一個(gè)配置文件類(lèi)ConfigProperties:
- @Data
- @Component
- public class ConfigProperties {
- @Value("${conf.url}")
- private String url;
- @Value("${conf.password}")
- private String password;
- }
配置文件中的配置屬性注入到該類(lèi),以供后續(xù)使用。
創(chuàng)建一個(gè)Controller類(lèi),用來(lái)測(cè)試驗(yàn)證,是否能夠正常運(yùn)行:
- @RestController
- @RequestMapping("/")
- public class ConfigController {
- @Resource
- private ConfigProperties configProperties;
- @RequestMapping
- public void print(){
- System.out.println(configProperties.getUrl());
- System.out.println(configProperties.getPassword());
- }
- }
對(duì)應(yīng)ConfigProperties類(lèi),application.properties中配置如下:
- conf.url=127.0.0.1
- conf.password=admin123
此時(shí),啟動(dòng)項(xiàng)目,訪問(wèn)Controller,能夠正常打印出配置信息,說(shuō)明程序可以正常運(yùn)行。
但配置文件中直接明文展示了password項(xiàng),如果別人看到該配置文件,就可能導(dǎo)致密碼的泄露。
基于Jasypt的加密
針對(duì)上述情況,通常,我們會(huì)對(duì)敏感信息進(jìn)行加密,避免明文密碼信息暴露,提升安全等級(jí)。
加密的基本思路是:配置文件中存儲(chǔ)加密內(nèi)容,在解析配置文件注入時(shí)進(jìn)行解密。
但如果拿到項(xiàng)目源碼,知道加密算法和秘鑰,肯定是可以解密的。這里的加密,只是多一層安全防護(hù),但并不是萬(wàn)能的。
下面看看如何基于Jasypt來(lái)進(jìn)行加密處理。
集成步驟
下面基于上述Spring Boot項(xiàng)目進(jìn)行改造升級(jí)。
環(huán)境準(zhǔn)備
不同版本的Jasypt使用方法有所不同,這里基于3.0.4版本、JDK8、Spring Boot 2.5.5來(lái)進(jìn)行演示。
在使用之前,首先檢查一下JDK8的JRE中是否安裝了不限長(zhǎng)度的JCE版本,否則在執(zhí)行加密操作時(shí)會(huì)拋出解密失敗的異常。
進(jìn)入$JAVA_HOME/jre/lib/security目錄,查看是否包含local_policy.jar和US_export_policy.jar兩個(gè)jar包。如果不包含,則通過(guò)Oracle官網(wǎng)進(jìn)行下載,下載地址:https://www.oracle.com/java/technologies/javase-jce8-downloads.html。
下載文件為:jce_policy-8.zip
文件內(nèi)包含三個(gè)文件:
- README.txt
- local_policy.jar
- US_export_policy.jar
查看$JAVA_HOME/jre/lib/security目錄下是否有這兩個(gè)jar包文件,如果沒(méi)有則復(fù)制進(jìn)去,如果有可考慮覆蓋。
引入依賴
在Spring Boot中集成Jasypt比較簡(jiǎn)單,直接引入如下依賴即可:
- <dependency>
- <groupId>com.github.ulisesbocchio</groupId>
- <artifactId>jasypt-spring-boot-starter</artifactId>
- <version>3.0.4</version>
- </dependency>
此時(shí),Jasypt組件自動(dòng)配置便已經(jīng)生效,只需要對(duì)需要加密的數(shù)據(jù)進(jìn)行處理了。
為了方便對(duì)密碼進(jìn)行加密,還可以在pom.xml中的build元素中引入對(duì)應(yīng)的plugin,這個(gè)后面會(huì)用到:
- <plugin>
- <groupId>com.github.ulisesbocchio</groupId>
- <artifactId>jasypt-maven-plugin</artifactId>
- <version>3.0.4</version>
- </plugin>
至此,所有的準(zhǔn)備工作已經(jīng)完成。
內(nèi)容加密
內(nèi)容加密有多種方式,這里挑選兩種方式進(jìn)行介紹。
方式一:?jiǎn)卧獪y(cè)試類(lèi)生成密文;
構(gòu)建如下單元測(cè)試類(lèi),使用默認(rèn)實(shí)例化的StringEncryptor對(duì)密碼進(jìn)行加密:
- @SpringBootTest
- class SpringBootJasyptApplicationTests {
- @Autowired
- private StringEncryptor stringEncryptor;
- @Test
- void contextLoads() {
- String qwerty1234 = stringEncryptor.encrypt("admin123");
- System.out.println(qwerty1234);
- }
- }
其中,”admin123“便是要加密的內(nèi)容。執(zhí)行上述程序,便可打印加密后的內(nèi)容。這種形式加密的內(nèi)容,全部采用默認(rèn)值。
方式二:通過(guò)Maven插件生成密文
在上面已經(jīng)引入了Jasypt的Maven插件,可通過(guò)對(duì)應(yīng)的命令進(jìn)行生成密碼。
第一步:在配置文件中添加加密的密碼:
- jasypt.encryptor.password=afx11
然后對(duì)配置文件中需要加密的數(shù)據(jù)進(jìn)行改造,在數(shù)據(jù)前添加”DEC(“,在數(shù)據(jù)尾部加上")",修改完如下:
- conf.password=DEC(admin123)
這里添加的DEC()是告訴插件,此部分內(nèi)容需要進(jìn)行加密處理。注意這里關(guān)鍵字是DEC。
第二步:執(zhí)行Maven命令,對(duì)上述數(shù)據(jù)進(jìn)行加密處理
在命令執(zhí)行以下命令:
- mvn jasypt:encrypt -Djasypt.encryptor.password=afx11
此時(shí)再看配置文件中的conf.password數(shù)據(jù)已經(jīng)變?yōu)椋?/p>
- jasypt.encryptor.password=afx11
- conf.url=127.0.0.1
- conf.password=ENC(209eBdF3+jsV2f8kDjs4NOCzgBxnVgETlR5q2KfhYo5DW2jqvLknv0TndEkXOXm0)
注意原來(lái)的DEC變成了ENC,原來(lái)的明文密碼變成了加密的密文。
此時(shí),如果想查看明文,執(zhí)行以下命令即可:
- mvn jasypt:decrypt -Djasypt.encryptor.password=afx11
該命令不會(huì)修改配置文件中的密文為明文,只會(huì)在控制臺(tái)進(jìn)行明文結(jié)果的輸出。
- jasypt.encryptor.password=afx11
- conf.url=127.0.0.1
- conf.password=DEC(admin123)
經(jīng)過(guò)上述操作,所有改造步驟已經(jīng)完成,只需啟動(dòng)系統(tǒng)進(jìn)行驗(yàn)證即可。
密碼的傳遞方式
完成上述步驟,直接啟動(dòng)系統(tǒng),訪問(wèn)對(duì)應(yīng)的請(qǐng)求,會(huì)發(fā)現(xiàn)已經(jīng)能夠成功打印出密碼原文了。
上述實(shí)例中我們將加密的密碼放在了application.properties文件中,這樣并不安全,如果查看代碼就知道如何解密了。通常,還可以采用另外一種形式來(lái)傳遞參數(shù):在啟動(dòng)命令中傳輸密碼。
比如:
- java -jar jasypt-spring-boot-demo-0.0.1-SNAPSHOT.jar --jasypt.encryptor.password=password
這樣,密碼便不用存儲(chǔ)在代碼當(dāng)中了,一定程度上增加了安全性。當(dāng)然,也可以通過(guò)環(huán)境變量來(lái)進(jìn)行傳遞,這樣即便開(kāi)發(fā)人員也無(wú)法獲得生產(chǎn)的密碼。
小結(jié)
關(guān)于Jasypt的使用及與Spring Boot的集成就講這么多,更多內(nèi)容也可參考官方文檔說(shuō)明。如果你的項(xiàng)目中還存在很多明文存儲(chǔ)的密碼,真的有必要考慮使用類(lèi)似的框架進(jìn)行加密處理了。
示例源碼地址:https://github.com/secbr/springboot-all/tree/master/springboot-jasypt
官方源碼地址:https://github.com/ulisesbocchio/jasypt-spring-boot