开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1 天,点击查看详情
该文章只包含数据库明文地址/密码/用户名加密,不包含用户信息加密内容.
需求:当前需求为在SpringCloud项目中隐藏Nacos配置文件中的数据库连接用户名密码等明文信息;要求使用密钥加密明文密码后将密钥使用明文盐值再次加密,明文盐值可见,项目启动自动获取盐值解密密钥,通过密钥解密密码进行数据库连接;
使用技术为Jasypt,版本为3.0.3,该版本可以使用简便方式进行数据库等信息加密解密,使用简单;
使用依赖:
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
解密通过实现StringEncryptor接口重写解密方法达到自定义解密方法解密需求;
自定义解密配置
@Configuration
public class JasyPtEncryptionConfig {
@Bean("jasyptStringEncryptor")
public StringEncryptor stringEncryptor() {
DESEncrypt desEncrypt = new DESEncrypt();
return desEncrypt;
}
}
自定义加密、解密方法
@Slf4j
public class DESEncrypt implements StringEncryptor {
@Value("${jasypt.encryptor.passSecret}")
private String passSecret;
@Override
public String encrypt(String s) {
return null;
}
/**
* 解密
*
* @param pass 加密的密码/用户名等信息
* @return
*/
@Override
public String decrypt(String pass) {
//启动类获取
String secretB = System.getProperty("jasypt.encryptor.secretB");
if (StringUtils.isBlank(pass) && StringUtils.isBlank(secretB)) {
log.error("当前获取密钥错误");
return null;
}
//先用获取的b密钥解密a
String decryptSecretA = decryptPass(passSecret, secretB);
//再用a解密数据库密码等
String outPass = decryptPass(pass, decryptSecretA);
System.out.println(outPass);
return outPass;
}
public String decryptPass(String encryptedText, String factor) {
// 1. 创建加解密工具实例
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
// 2. 加解密配置
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword(factor);
config.setAlgorithm("PBEWITHHMACSHA512ANDAES_256");
// 为减少配置文件的书写,以下都是 Jasyp 3.x 版本,配置文件默认配置
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);
// 3. 解密
return encryptor.decrypt(encryptedText);
}
public static String decryptWithSHA512(String plainText, String factor) {
// 1. 创建加解密工具实例
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
// 2. 加解密配置
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword(factor);
config.setAlgorithm("PBEWITHHMACSHA512ANDAES_256");
// 为减少配置文件的书写,以下都是 Jasyp 3.x 版本,配置文件默认配置
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);
// 3. 解密
return encryptor.decrypt(plainText);
}
public static String encryptWithSHA512(String plainText, String factor) {
// 1. 创建加解密工具实例
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
// 2. 加解密配置
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
config.setPassword(factor);
config.setAlgorithm("PBEWITHHMACSHA512ANDAES_256");
// 为减少配置文件的书写,以下都是 Jasyp 3.x 版本,配置文件默认配置
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);
// 3. 加密
return encryptor.encrypt(plainText);
}
public static void main(String[] args) {
UUID randomUUID = UUID.randomUUID();
String uuid = randomUUID.toString().replace("-", "");
String s = encryptWithSHA512(uuid, "secretB");
System.out.println("需要设定的密钥:" + s);
String s1 = encryptWithSHA512("${MYSQL-PWD:***}", uuid);
System.out.println("密码:" + s1);
String s2 = encryptWithSHA512(
"jdbc:mysql://${MYSQL-HOST:***}:${MYSQL-PORT:3306}/${MYSQL-DB:nacos}?characterEncoding=utf8&connectTimeout=10000&socketTimeout=30000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true",
uuid);
System.out.println("地址:" + s2);
String s3 = encryptWithSHA512("${MYSQL-USER:***}", uuid);
System.out.println("用户名:" + s3);
String s4 = decryptWithSHA512(s1, uuid);
System.out.println("解密密码:" + s4);
}
}
其中加密过的密钥保存再配置文件中
jasypt:
encryptor:
algorithm: PBEWITHHMACSHA512ANDAES_256
passSecret: 加密过的密钥
明文盐值放置在启动命令中
-Djasypt.encryptor.secretB=secretB

配置文件中密码、用户名使用ENC()包裹即可实现;
db:
num: 1
password:
'0': ENC(3fg2aEiqqQyDU3ZSd8GMJa0p2U+O4rDd+vdmRMx0b2ZEoNnPTaYjY2vzo56kzWdUkzImCIqCXDrfTn1pYNCW4g==)
url:
'0': ENC(pGIlhA1s221wtfRPgI6sNDWhmBUS1VjeCyg2UmNbT3nd06Pmqj5o5zi2R5VS9D5X1m6tfOkqch9bbvzKm84wkxctt763YkqAEZkcpDYkY/ZYN6ZbLE2qGlyC3TUXsCXd0o/47Wr2JxRRHcS/aYOm2MRlBkGyB6DLibDU3uZs+l84NDSm3K2SNdUsQdMNrVwSt0jCYKilqVFZDLQDJkwpgZCfcMxcF/ySylD4w3qcsSGs702Nrtt/n8R9EeN7wPQLovZbhNT9yZGCFmUl005XnO24ggGjTQ31EQaYFq30yp3AL6dpl+urZDck6Y1xjpNPK4YGxXJ2/NLOjCvr2IpvArKPjxPNl7Mc8yEA+BxA63U=)
user:
'0': ENC(g8KrO5Wm7+ojgfHaI8lYfudzbpCgN4a)
注意问题:使用3.0.3版本会出现 # Failed to bind properties under ‘xxx.xxx.xxx‘ to java.lang.String 首先检查代码逻辑,代码逻辑无问题可以尝试替换文件; 文件地址:
1、打开以下网址,下载JCE压缩包:
JCE Unlimited Strength Jurisdiction Policy Files for JDK/JRE 8 Download
2、把解压出来的local_policy.jar、US_export_policy.jar替换掉jdk1.8.0_144/jre/lib/security下的2个jar包(先备份后替换)