2021.2.24 更新
1 概述
Jasypt
是一個加密庫,Github
上有一個集成了Jasypt
的Spring Boot
庫,叫jasypt-spring-boot
,本文演示了如何使用該庫對配置文件進行加密。
2 依賴
首先添加依賴:
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
Gradle
:
implementation("com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.3")
3 簡單加密
簡單加密就是直接把加密口令(注意不是加密密碼)以明文形式寫在配置文件中,步驟如下:
- 配置文件配置加密口令
- 獲取密文
- 替換明文
3.1 加密口令
在配置文件加上如下參數:
jasypt:
encryptor:
password: test
其中test
就是加密的口令。
3.2 獲取密文
比如配置文件需要加密的值如下:
test: value
在測試類對StringEncryptor
進行注入並使用其中的encrypt
加密通過@Value
獲取的值:
@SpringBootTest
class DemoApplicationTests {
@Autowired
private StringEncryptor encryptor;
@Value("${test}")
private String value;
@Test
void contextLoads() {
System.out.println(encryptor.encrypt(value));
}
}
點擊旁邊的綠色小三角形即可運行,輸出如下:
這個就是對應的密文。
3.3 替換明文
把密文加上前綴ENC(
與后綴)
替換明文:
test: ENC(IlEvyvcULhZJrHLDtPun2ut433RvAdpaNJ9IZt9uNUk3hDSKQsdOXLEkWyiK6QR3)
這樣就完成了對屬性test
進行加密。
3.4 測試
直接通過@Value
獲取的值即為明文:
@SpringBootTest
class DemoApplicationTests {
@Autowired
private StringEncryptor encryptor;
@Value("${test}")
private String value;
@Test
void contextLoads() {
System.out.println(encryptor.encrypt(value));
}
@Test
void decrypt()
{
System.out.println(value);
}
}
直接運行其中的decrypt
即可輸出明文。
4 自定義加密
4.1 自定義加密類
默認采用的加密算法為PBE
算法,如果覺得不能符合要求可以自定義加密類。
自定義加密類實現StringEncrypto
接口即可,需要在配置文件寫上Bean
的名稱:
@Component
public class Encryptor implements StringEncryptor{
@Override
public String encrypt(String s) {
return s+"111";
}
@Override
public String decrypt(String s) {
return s.substring(0,s.indexOf("111"));
}
}
這里的加密很簡單,直接在明文后面加上111
,解密的話去掉111
。另外在配置文件上寫上Bean
的名稱:
jasypt:
encryptor:
# password: test
bean: encryptor
同時可以把口令注釋掉,因為此時已經不需要使用口令進行加密了。
測試:
@SpringBootTest
class DemoApplicationTests {
@Autowired
private StringEncryptor encryptor;
@Value("${test}")
private String value;
@Test
void contextLoads() {
System.out.println(encryptor.encrypt(value));
}
@Test
void decrypt()
{
System.out.println(encryptor.decrypt(value));
}
}
4.2 非對稱加密
生成公鑰與私鑰借助了工具類庫Hutool
,依賴如下:
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-crypto</artifactId>
<version>5.4.3</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.66</version>
</dependency>
Gradle
:
implementation("cn.hutool:hutool-crypto:5.4.3")
implementation("org.bouncycastle:bcprov-jdk15on:1.66")
生成公鑰私鑰:
KeyPair pair = SecureUtil.generateKeyPair("RSA");
System.out.println(Base64.getEncoder().encodeToString(pair.getPublic().getEncoded()));
System.out.println(Base64.getEncoder().encodeToString(pair.getPrivate().getEncoded()));
生成后添加到jasypt.encryptor.public-key-string
與jasypt.encryptor.private-key-string
:
jasypt:
encryptor:
# password: test
# bean: encryptor
public-key-string: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCZV5U0+Ck4AEpawUoiHOkG4ZNC6EeEvFZVCcyaIM0MiusGMM6ye9ZT6Ok756/vQsJbsYDGDtIDX82TsmYbZkN7QPuclABSL5SmaDYdJM/MeYKfMwrDb0lWARqF5ql9Rgol7Agq4ef8yQEbSmUDW/LQe+xXtCTer5MoJViUHV56MwIDAQAB
private-key-string: MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAJlXlTT4KTgASlrBSiIc6Qbhk0LoR4S8VlUJzJogzQyK6wYwzrJ71lPo6Tvnr+9CwluxgMYO0gNfzZOyZhtmQ3tA+5yUAFIvlKZoNh0kz8x5gp8zCsNvSVYBGoXmqX1GCiXsCCrh5/zJARtKZQNb8tB77Fe0JN6vkyglWJQdXnozAgMBAAECgYA8syFCrwtt+ht00ne8ijIqQagP/6+z2PPZxL/DsUFJ+kGvmSlxGLlOTO/qgTuxG/2g22JsxFgY8tcHZMKrjO8f4TLKPsaFgX1OwNhJO4SoMlfUUAR9HSMv49vx5mOvh2QUrC5+4rIQI1Rm8zbKyAqCjHIKr8hA6bIKEHO2qXK05QJBANhAA+djwrr3orIIBTRp+H6/JChH76XtoQfcQyT+CrEu/4tHVkbO2cEqcdKDScswHyTPu5UaSU2HFW/0Lj8Kg40CQQC1h1YMysd51djCf/Ud7L2sSIduy3DUSLc6XRX1IWAqxO+8gkvknDW7QztNES9YqwYEkLNLAjp1v8Gq+o2JQKS/AkAENCpfQycz70BwaYuAW1cDT7/qMIvOE/J/bp63h2C51QoOsRJSSg8dnC+eQgMbOhJA6vDgkyQ9p5SZGowTmaa5AkEAneQAIZJC3KL3LX20ivm+pFpVijXjhpFU5avPjG4iQjEXQISoVEjWp3G747V91Aa1bkUZ3bUref13Cytw7h/O6wJBAJHNIHKKTAkmslguJU5hll1HqrzyI9lcB5XqcgvdsxijUkZ95FThk6hNQuNV0sO/itUijQsJAtNdDITKmdcPMWg=
然后就可以像加密得到密文並替換明文了。
5 非明文口令
對於jasypt.encryptor.password
,可以使用非明文口令,這樣口令的傳遞方式有三種:
- 通過命令行參數傳遞
- 通過應用環境變量傳遞
- 通過系統環境變量傳遞
5.1 通過命令行參數傳遞
首先先寫上明文口令,得到密文:
jasypt:
encryptor:
password: test
test: value
加上前后綴替換明文后,去掉加密口令:
#jasypt:
# encryptor:
# password: test
test: ENC(quCu1b+Z7SPHmgVsmbkeyNZmNe1LJw+SxjmwwLjNaWoH/ce3r6iHGvaMN5eQcu0P)
並在測試類的參數類加上
--jasypt.encryptor.password=test
由於這里是測試類命令行參數添加不了,但是在啟動類是可以添加的:
這種方法就跳過演示了。
對於Gradle
,測試的時候需要在build.gradle
/build.gradle.kts
添加參數:
tasks.withType<Test> {
useJUnitPlatform()
jvmArgs("-Djasypt.encryptor.password=test")
// 不能是jvmArgs("--jasypt.encryptor.password=test")
}
5.2 通過應用環境變量傳遞
和第一種方式差不多,第一種在Program arguments
設置,而這種方法在VM options
中設置:
-Djasypt.encryptor.password=test
5.3 系統環境變量方式傳遞
通過系統環境變量方式傳遞jasypt.encryptor.password
時,需要指定是哪一個環境變量:
jasypt:
encryptor:
password: ${ENCRYPT}
比如這里指定的是ENCRYPT
環境變量,設置好環境變量后就可以直接加密解密了。
6 部署注意事項
6.1 打包
因為在配置文件中缺少了jasypt.encryptor.password
,因此使用Maven
打包時會出錯:
在Maven
打包配置中加上參數即可:
但是使用Gradle
打包時不需要添加額外的參數。
6.2 部署
現在一般通過JAR
直接部署即可,也就是通過
java -jar demo.jar
部署,這時候根據需要加上對應的參數即可,比如:
java -jar demo.jar --jasypt.encryptor.password=test
java -Djasypt.encryptor.password=test -jar demo.jar
如果通過系統變量獲取加密口令,請確保對應的環境變量存在。
另外,如果通過Docker
部署,請在ENTRYPOINT
加上對應參數,比如:
ENTRYPOINT ["java","-Djasypt.encryptor.password=test","-jar","demo.jar"]
ENTRYPOINT ["java","-jar","demo.jar",,"--jasypt.encryptor.password=test",]
通過系統環境變量獲取請加上ENV
:
ENV ENCRYPT="test"
7 參考源碼
Java
版:
Kotlin
版: