Jasypt是一個加密庫,Github上有一個集成了Jasypt的Spring Boot庫,叫jasypt-spring-boot,可以加密我們在源碼配置文件里面的有段的敏感信息,如用戶名密碼等,本文演示了如何使用該庫對配置文件進行加密。
一、先看一份典型的配置文件
...
## 配置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短信服務連接
aliyun.sms.access_key_id=3zHmLddxAes7Bbe21
aliyun.sms.access_key_secret=b3mWd36iy0him8tr
...
這是節(jié)選自某個典型的Spring Boot項目的application.properties配置文件。這乍一看沒啥問題,很多人會覺得理所當然。初期我的開源項目也是這樣寫的,直到某天我突然想到,如果大家拿項目里面的配置信息直接連接我的數(shù)據(jù)庫,然后刪除掉我數(shù)據(jù)庫的所有數(shù)據(jù),那世界上不就又多了一個傷心的人了。

所以,為了保證項目的安全,我們通用做法是將SpringBoot的配置文件中敏感并且重要的信息進行加密處理。
二、使用jasypt-spring-boot加密配置文件
1、引入jasypt-spring-boot加密組件
maven:在項目pom中添加如下代碼
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
Gradle
implementation("com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.4")
2、配置加密密鑰
在Spring Boot的項目配置文件application.properties里新增如下配置:
jasypt.encryptor.password=CodeSheep
3、加密測試
為了便于測試,我們直接擴展Spring Boot項目的啟動類,項目啟動時執(zhí)行加密測試代碼,直接看效果
@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");
// 加密
String mysqlEncryptedPswd = encrypt( mysqlOriginPswd );
String redisEncryptedPswd = encrypt( redisOriginPswd );
String aliSmsEncryptedAk = encrypt( aliSmsOriginAk );
// 打印加密前后的結果對比
System.out.println( "MySQL原始明文密碼為:" + mysqlOriginPswd );
System.out.println( "Redis原始明文密碼為:" + redisOriginPswd );
System.out.println( "阿里云SMS原始AccessKey密碼為:" + aliSmsOriginAk );
System.out.println( "====================================" );
System.out.println( "MySQL原始明文密碼加密后的結果為:" + mysqlEncryptedPswd );
System.out.println( "Redis原始明文密碼加密后的結果為:" + redisEncryptedPswd );
System.out.println( "阿里云SMS原始AccessKey密碼加密后的結果為:" + aliSmsEncryptedAk );
}
private String encrypt( String originPassord ) {
String encryptStr = codeSheepEncryptorBean.encrypt( originPassord );
return encryptStr;
}
private String decrypt( String encryptedPassword ) {
String decryptStr = codeSheepEncryptorBean.decrypt( encryptedPassword );
return decryptStr;
}
}
運行項目,控制臺打?。?/p>
MySQL原始明文密碼為:123456
Redis原始明文密碼為:111111
阿里云SMS原始AccessKey密碼為:bImWdv13da894mly
====================================
MySQL原始明文密碼加密后的結果為:IV7SyeQOfG4GhiXeGLboVgOLPDO+dJMDoOdmEOQp3KyVjruI+dKKeehsTriWPKbo
Redis原始明文密碼加密后的結果為:litUkxJ3fN6+//Emq3vZ+y4o7ZOnZ8doOy7NrgJIDLoNWGG0m3ygGeQh/dEroKvv
阿里云SMS原始AccessKey密碼加密后的結果為:MAhrOs20DY0RU/c1IKyLCt6dWZqLLOO4wUcK9GBgSxNII3C+y+SRptors+FyNz55xNDslhDnpWllhcYPwZsO5A==
4、修改配置文件,替換待加密配置項
我們拿到上一步得到的加密結果,將配置文件中的原始明文密碼替換成上一步對應的結果即可,就像這樣:

所以強烈建議配置文件里的所有重要信息都這樣處理!
5、查看密碼解密結果
@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()語法包裹的配置項加密字段自動解密,數(shù)據(jù)得以還原。
這時候我想肯定很多小伙伴表示疑惑,典型的比如:
1、加密密鑰必須放在ENC()中?為什么是ENC?
2、雖然說原始涉及信息安全的配置項被加密,但是自定義的加密密鑰jasypt.encryptor.password=CodeSheep假如泄露了,別人不還是有幾率可以解密的嗎?
針對這些問題,繼續(xù)往下看。
三、自定義加密前后綴
如果不愿意使用jasypt默認提供的ENC來標記加密字段,完全可以換成自定義的前后綴標記,比如我想換成CodeSheep()來標記加密字段,此時只需要在配置文件里配置一下前后綴即可:
jasypt.encryptor.property.prefix=CodeSheep(
jasypt.encryptor.property.suffix=)

四、讓加密更安全
雖然經(jīng)過上文的加密,涉及信息安全的配置項肯定會變得更安全,這個毋庸置疑!
但是假如配置文件里的自定義加密密鑰jasypt.encryptor.password=CodeSheep泄露了,那我們的加密字段也還是有可能被別人解密,為此,有幾項工作可以讓加密變得更加安全。
1、使用自定義加密器
上文實驗加密時,使用的是默認的加密規(guī)則,這一點會讓當自定義加密密鑰泄漏時可能變得不安全。為此我們可以自定義加密規(guī)則。
自定義加密規(guī)則非常簡單,只需要提供自定義的加密器配置類即可,比如我這里自定義一個名為 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、加密密鑰不要寫在配置文件中
如果覺得上面這種方式還是可能會導致加密密鑰泄露的話(畢竟還是寫在了配置文件中),那我們干脆可以直接將加密密鑰從配置文件中拿掉,取而代之的有三種方式:
- 方式一:直接作為程序啟動時的命令行參數(shù)來帶入
java -jar yourproject.jar --jasypt.encryptor.password=CodeSheep
- 方式二:直接作為程序啟動時的應用環(huán)境變量來帶入
java -Djasypt.encryptor.password=CodeSheep -jar yourproject.jar
- 方式三:甚至可以作為系統(tǒng)環(huán)境變量的方式來帶入
比方說,我們提前設置好系統(tǒng)環(huán)境變量JASYPT_ENCRYPTOR_PASSWORD = CodeSheep,則直接在Spring Boot的項目配置文件中做如下配置即可:
jasypt.encryptor.password=${JASYPT_ENCRYPTOR_PASSWORD:}
這時候也會安全得多。噓…好了,說了這么多,如果你項目的配置文件中的重要信息沒有加密的話,答應我,二話別說,趕快全部偷偷去改掉,快!速度!跑步前進!