SpringBoot配置文件中敏感信息加密的三種方法
一. 背景
當(dāng)我們將項目部署到服務(wù)器上時,一般會在jar包的同級目錄下加上application.yml配置文件,這樣可以在不重新?lián)Q包的情況下修改配置。
一般會將數(shù)據(jù)庫連接、Redis連接等放到配置文件中。
例如配置數(shù)據(jù)庫連接:
spring: servlet: multipart: max-file-size: 10MB # 文件大小限制 max-request-size: 100MB # 請求大小限制 datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai username: root password: 123456
這種方式存在安全隱患,如果配置文件泄露,就會造成數(shù)據(jù)庫密碼泄露。
所以需要將配置文件中數(shù)據(jù)庫密碼等敏感數(shù)據(jù)加密,然后在使用的時候解密后再使用。
推薦使用第三種方式。
二. 方法介紹
本文介紹三種方式。
1. 解密方法嵌入到業(yè)務(wù)邏輯代碼中
例如我可以在service或者正常的業(yè)務(wù)代碼中去加密后再使用。
但是這種和業(yè)務(wù)耦合度高,不推薦。
2. 使用jasypt
2.1 第一步:pom引入依賴
<dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>jasypt-spring-boot-starter</artifactId> <version>2.1.2</version> </dependency>
2.2 第二步:application.yml中增加jasypt配置
配置文件里配置該算法加解密的鹽值。jaspypt算法不需要我們自己實現(xiàn),該第三方庫已經(jīng)實現(xiàn)了。我們僅需要配置這個鹽值即可。
# 如果密文加鹽,需要配置鹽值 jasypt: encryptor: password: ueiej@8e8r
2.3 第三步:application.yml中密文替代明文。
配置文件里將加密后得到的密文用ENC(密文)
方式配置即可。項目啟動的時候,程序會自動去解析配置文件中值為ENC(密文)
格式的配置,然后解密后加載程序。
數(shù)據(jù)的加密可以自己實現(xiàn)工具類來加密,或者一些在線網(wǎng)站提供jasypt的加解密,得到加密后的密文后,將密文替換明文即可。
例如:
password: ENC(UBHpSHxjL2F8ZiNTJUciZw==)
到此就全部結(jié)束了。項目啟動的時候程序會自動去解密,并注入到實際的springApplication中。
優(yōu)缺點
優(yōu)點:是引入第三方庫,簡單匹配一下即可,業(yè)務(wù)代碼不需要任何改動。
缺點:是把jasypt的鹽放到配置文件中,那實際上你的加密數(shù)據(jù)也跟裸奔一樣了,別人一樣可以用這個jasypt解密得到你的數(shù)據(jù)庫密碼等加密數(shù)據(jù)。
3. 使用自定義加解密算法并自動裝配
3.1 第一步:確定加解密規(guī)則,編寫工具類
我們可以自定義加解密算法來實現(xiàn)數(shù)據(jù)的加解密,這里采用AES算法。工具類的代碼省略。
3.2 第二步:實現(xiàn)EnvironmentPostProcessor
Spring Boot沒有為加密屬性值提供任何內(nèi)置支持。 EnvironmentPostProcessor 接口允許你在應(yīng)用程序啟動前操作 Environment,可以用來修改Spring Environment 中包含的值。實現(xiàn)接口,并在接口里遍歷所有的配置項,將指定的配置項解密后重新寫入Environment。
示例:
public class DecryptEnvironmentPostProcessor implements EnvironmentPostProcessor { @Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { Properties props = new Properties(); // 臨時存儲需要替換的配置 // 假設(shè)加密密碼前綴為 "ENC(",后綴為 ")" MutablePropertySources propertySources = environment.getPropertySources(); for (PropertySource<?> propertySource : propertySources) { if (propertySource instanceof EnumerablePropertySource) { EnumerablePropertySource<?> enumerablePropertySource = (EnumerablePropertySource<?>) propertySource; String[] propertyNames = enumerablePropertySource.getPropertyNames(); // 遍歷所有配置key:value for (String propertyName : propertyNames) { String propertyVal = environment.getProperty(propertyName); // 根據(jù)自己寫的規(guī)則來解析那些配置是需要解密的 if (propertyVal != null && propertyVal.startsWith("ENC(") && propertyVal.endsWith(")")) { // 解析得到加密的數(shù)據(jù) String encryptedValue = propertyVal.substring(4, propertyVal.length() - 1); // 調(diào)用自定義工具類解密 String decryptedValue = AESUtil.decryptEcbMode(encryptedValue); // 保存需要替換的配置 props.put(propertyName, decryptedValue); } } } } // 添加解密后的屬性到環(huán)境中 if (!props.isEmpty()) { PropertiesPropertySource pps = new PropertiesPropertySource("decryptedProperties", props); environment.getPropertySources().addFirst(pps); } } }
3.3 自動裝配
在resources/META-INF/spring.factories
中注冊EnvironmentPostProcessor
。
org.springframework.boot.env.EnvironmentPostProcessor=\ your.package.DecryptEnvironmentPostProcessor
這里把自己實現(xiàn)的.DecryptEnvironmentPostProcesso的全路徑放進(jìn)去即可。
沒有META-INF/spring.factories文件的,直接建好目錄新增這個文件就行。
3.4 配置文件密文替換明文
使用自定義的工具類將密碼加密,得到密文。用密文替換配置中的密文。
這里我依然使用ENC(密文)
的格式去配置,這個規(guī)則可以自己定義,只要修改DecryptEnvironmentPostProcessor的方法中的匹配邏輯即可。
例如:
spring: datasource: password: ENC(你的加密密碼)
注意事項
你可以寫死你的加密的配置項,然后在postProcessEnvironme()方法里找到對應(yīng)的配置項解密?;蛘吣憧梢詫⒓用艿乃袛?shù)據(jù)都用ENC(加密的數(shù)據(jù))表示,然后在postProcessEnvironme方法里匹配后解密即可。當(dāng)然這里的編寫規(guī)則你可以自己定義,只要能匹配出來即可。
例如我的配置如下:
spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai username: root password: ENC(UBHpSHxjL2F8ZiNTJUciZw==)
其中數(shù)據(jù)庫的密碼就是AES算法解密后的結(jié)果。
總結(jié)
建議用第三種方式,因為這種加密算法可以自定義,并且不需要把加解密的秘鑰放到配置文件里,即便有人拿到配置文件,也無法得到真實的密碼,更加的安全。
而且第三種方式對業(yè)務(wù)代碼沒有侵入,也不需要特定引入第三方庫和配置其他東西。
以上就是SpringBoot配置文件中敏感信息加密的三種方法的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot敏感信息加密的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
一文帶你掌握J(rèn)ava?ReentrantLock加解鎖原理
這篇文章將為大家詳細(xì)介紹一下Java中ReentrantLock?加鎖和釋放鎖的原理,以及和?Synchronized?的對比。文中的示例代碼講解詳細(xì),希望對大家有所幫助2022-12-12Spring 應(yīng)用上下文獲取 Bean 的常用姿勢實例總結(jié)
這篇文章主要介紹了Spring 應(yīng)用上下文獲取 Bean,結(jié)合實例形式總結(jié)分析了Spring 應(yīng)用上下文獲取 Bean的實現(xiàn)方法與操作注意事項,需要的朋友可以參考下2020-05-05Java實現(xiàn)將Markdown轉(zhuǎn)換為純文本
這篇文章主要為大家詳細(xì)介紹了兩種在 Java 中實現(xiàn) Markdown 轉(zhuǎn)純文本的主流方法,文中的示例代碼講解詳細(xì),大家可以根據(jù)需求選擇適合的方案2025-03-03Java 比較接口comparable與comparator區(qū)別解析
這篇文章主要介紹了Java 比較接口comparable與comparator區(qū)別解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-10-10最簡單的在IntelliJ IDEA導(dǎo)入一個本地項目教程(圖文)
這篇文章主要介紹了最簡單的在IntelliJ IDEA導(dǎo)入一個本地項目教程(圖文),文中通過圖文介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08一文了解Java讀寫鎖ReentrantReadWriteLock的使用
ReentrantReadWriteLock稱為讀寫鎖,它提供一個讀鎖,支持多個線程共享同一把鎖。這篇文章主要講解一下ReentrantReadWriteLock的使用和應(yīng)用場景,感興趣的可以了解一下2022-10-10Spring框架的ImportSelector詳細(xì)解讀
這篇文章主要介紹了Spring框架的ImportSelector詳細(xì)解讀,Spring中一個非常重要的注解@Import中的ImportSelector接口的作用以及它到底有啥作用,也會捎帶一部分源碼說一下DeferredImportSelector是干啥的,需要的朋友可以參考下2024-01-01