配置MySQL資料庫連接配接
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://121.196.xxx.xxx:3306/user?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=123456
配置Redis緩存連接配接
redis.host=121.196.xxx.xxx
redis.port=6379
redis.password=111111
配置SMS短信服務連接配接
ali.sms.access_key_id=2zHmLdxAes7Bbe2w
ali.sms.access_key_secret=bImWdv6iy0him8ly
這是典型的Spring Boot項目的application.properties配置檔案。
一般來說,項目配置檔案裡,所有涉及資訊安全的配置項(或字段)都應該做處理,典型的比如:
用到的資料庫、緩存的密碼
用到的中間件、消息隊列的密碼
用到的各種第三方服務的Access_Key
其他第三方服務的通信資訊
…等等
總而言之,關鍵字段都應該保護起來,最起碼不能用明文直接寫在配置檔案裡!
如何加密配置項呢?
方法非常簡單,幾個步驟即可完成,先來示範一個最簡版本:
1、首先建立一個基礎的Spring Boot工程
這就不再贅述了
2、引入jasypt-spring-boot加密元件
通過jasypt-spring-boot這個開箱即用的加密元件來引入Jasypt這個強大的加密庫
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
3、配置加密密鑰
在Spring Boot的項目配置檔案application.properties裡新增如下配置:
jasypt.encryptor.password=CodeSheep
可以了解為jasypt會使用這個自定義加密密鑰,對配置檔案裡的重要項進行加密。
4、加密測試
為了便于測試,我們直接擴充Spring Boot項目的啟動類,項目啟動時執行加密測試代碼,直接看效果
@SpringBootApplication
public class SpringBootConfigEncryptApplication implements CommandLineRunner {
@Autowired
private ApplicationContext appCtx;
@Autowired
private StringEncryptor codeSheepEncryptorBean;
public static void main(String[] args) {
SpringApplication.run(SpringBootConfigEncryptApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
Environment environment = appCtx.getBean(Environment.class);
// 首先擷取配置檔案裡的配置項
String mysqlOriginPswd = environment.getProperty("spring.datasource.password");
String redisOriginPswd = environment.getProperty("redis.password");
String aliSmsOriginAk = environment.getProperty("ali.sms.access_key_secret");
// 列印解密後的結果
System.out.println( "MySQL原始明文密碼為:" + mysqlOriginPswd );
System.out.println( "Redis原始明文密碼為:" + redisOriginPswd );
System.out.println( "阿裡雲SMS原始AccessKey密碼為:" + aliSmsOriginAk );
}
}
運作項目,控制台列印:
MySQL原始明文密碼為:123456
Redis原始明文密碼為:111111
阿裡雲SMS原始AccessKey密碼為:bImWdv13da894mly
=====================================
MySQL原始明文密碼加密後的結果為:IV7SyeQOfG4GhiXeGLboVgOLPDO+dJMDoOdmEOQp3KyVjruI+dKKeehsTriWPKbo
Redis原始明文密碼加密後的結果為:litUkxJ3fN6+//Emq3vZ+y4o7ZOnZ8doOy7NrgJIDLoNWGG0m3ygGeQh/dEroKvv
阿裡雲SMS原始AccessKey密碼加密後的結果為:MAhrOs20DY0RU/c1IKyLCt6dWZqLLOO4wUcK9GBgSxNII3C+y+SRptors+FyNz55xNDslhDnpWllhcYPwZsO5A==
5、修改配置檔案,替換待加密配置項
我們拿到上一步得到的加密結果,将配置檔案中的原始明文密碼替換成上一步對應的結果即可,就像這樣:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnLkBzY2ITY0YWO2Q2M1YDZ4kTNzQTNxkjYxATMlljM2I2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
是以牆裂建議配置檔案裡的所有重要資訊都這樣處理!
6、檢視密碼解密結果
@SpringBootApplication
public class SpringBootConfigEncryptApplication implements CommandLineRunner {
@Autowired
private ApplicationContext appCtx;
@Autowired
private StringEncryptor codeSheepEncryptorBean;
public static void main(String[] args) {
SpringApplication.run(SpringBootConfigEncryptApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
Environment environment = appCtx.getBean(Environment.class);
// 首先擷取配置檔案裡的配置項
String mysqlOriginPswd = environment.getProperty("spring.datasource.password");
String redisOriginPswd = environment.getProperty("redis.password");
String aliSmsOriginAk = environment.getProperty("ali.sms.access_key_secret");
// 列印解密後的結果
System.out.println( "MySQL原始明文密碼為:" + mysqlOriginPswd );
System.out.println( "Redis原始明文密碼為:" + redisOriginPswd );
System.out.println( "阿裡雲SMS原始AccessKey密碼為:" + aliSmsOriginAk );
}
}
列印結果:
MySQL原始明文密碼為:123456 Redis原始明文密碼為:111111
阿裡雲SMS原始AccessKey密碼為:bImWdv13da894mly
很明顯,在代碼中使用時,jasypt-spring-boot元件會自動将ENC()文法包裹的配置項加密字段自動解密,資料得以還原。
這時候我想肯定很多小夥伴表示疑惑,典型的比如:
1、加密密鑰必須放在ENC()中?為什麼是ENC?
2、雖然說原始涉及資訊安全的配置項被加密,但是自定義的加密密鑰jasypt.encryptor.password=CodeSheep假如洩露了,别人不還是有幾率可以解密的嗎?
針對這些問題,繼續往下看。
自定義加密前字尾
如果不願意使用jasypt預設提供的ENC來标記加密字段,完全可以換成自定義的前字尾标記,比如我想換成CodeSheep()來标記加密字段,此時隻需要在配置檔案裡配置一下前字尾即可:
jasypt.encryptor.property.prefix=CodeSheep(
jasypt.encryptor.property.suffix=)
這時候加密字段就可以放在CodeSheep()标記的字段中:
讓加密更安全
雖然經過上文的加密,涉及資訊安全的配置項肯定會變得更安全,這個毋庸置疑!
但是假如配置檔案裡的自定義加密密鑰jasypt.encryptor.password=CodeSheep洩露了,那我們的加密字段也還是有可能被别人解密,為此,有幾項工作可以讓加密變得更加安全。
1、使用自定義加密器
上文實驗加密時,使用的是預設的加密規則,這一點會讓當自定義加密密鑰洩漏時可能變得不安全。為此我們可以自定義加密規則。
自定義加密規則非常簡單,隻需要提供自定義的加密器配置類即可,比如我這裡自定義一個名為 codeSheepEncryptorBean類型的加密器:
@Configuration
public class CodeSheepEncryptorCfg {
@Bean( name = "codeSheepEncryptorBean" )
public StringEncryptor codesheepStringEncryptor() {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword("CodeSheep");
config.setAlgorithm("PBEWITHHMACSHA512ANDAES_256");
config.setKeyObtentionIterations("1000");
config.setPoolSize("1");
config.setProviderName("SunJCE");
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");
config.setStringOutputType("base64");
encryptor.setConfig(config);
return encryptor;
}
}
注意這裡Bean的名字name是需要顯式指定的(預設的名字是jasyptStringEncryptor),如果像這裡一樣用的自定義名字,則還需要在Spring Boot的application.properties配置檔案中來指定bean的名字,就像這樣:
jasypt.encryptor.bean=codeSheepEncryptorBean
2、加密密鑰不要寫在配置檔案中
如果覺得上面這種方式還是可能會導緻加密密鑰洩露的話(畢竟還是寫在了配置檔案中),那我們幹脆可以直接将加密密鑰從配置檔案中拿掉,取而代之的有三種方式:
方式一:直接作為程式啟動時的指令行參數來帶入
java -jar yourproject.jar --jasypt.encryptor.password=CodeSheep
方式二:直接作為程式啟動時的應用環境變量來帶入
java -Djasypt.encryptor.password=CodeSheep -jar yourproject.jar
方式三:甚至可以作為系統環境變量的方式來帶入
比方說,我們提前設定好系統環境變量JASYPT_ENCRYPTOR_PASSWORD = CodeSheep,則直接在Spring Boot的項目配置檔案中做如下配置即可:
jasypt.encryptor.password=${JASYPT_ENCRYPTOR_PASSWORD:}
這時候也會安全得多。