1、需求
1)密码配置不能显示为明文,有安全隐患;
2)要支持程序启动时动态加解密密文密码,且密钥也不能直接写在配置文件中;
3)相同的密码对应的密文不能一致,需要加盐处理;
2、解决办法
使用 jasypt 第三方库解决此问题,以数据库和redis密码为例:
测试的配置:
代码语言:bash复制spring.datasource.url: jdbc:mysql://172.20.1.1:3307/3306?useUnicode=true&characterEncoding=utf8&useSSL=true&verifyServerCertificate=false&trustServerCertificate=true&allowMultiQueries=true
spring.datasource.username: root
spring.datasource.password: root@123
spring.redis.password: root@123
上线的配置:
代码语言:bash复制spring.datasource.url: jdbc:mysql://172.20.1.1:3306/portal?useUnicode=true&characterEncoding=utf8&useSSL=true&verifyServerCertificate=false&trustServerCertificate=true&allowMultiQueries=true
spring.datasource.username: root
spring.datasource.password: ENC(jiLHnOdWJuHAOC6DsR2XmyJe7LuGWD l/3izm7bYjPdv5W6Ge8IqDNeylEBuS11e)
spring.redis.password: ENC(m xVkutzcODyHsXIeHtYgk6awNdFv69DiGHJXqbsfsjRsXOiHOu3WKkOq2OIJrYa)
这里可以看到,redis和mariadb相同的密码,其密文是不一致的。而且配置文件中不需要任何jasypt的配置。程序可以正常启动并解密。
操作说明:
这里只需要默认注册一个StringEncryptor的Bean即可,把密码写死在代码中。
代码语言:java复制@Configuration
public class DefaultJasyptConfig {
public static final String SALT_PASSWORD = "your_uuid";
@Bean("jasyptStringEncryptor")
public StringEncryptor stringEncryptor() {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
// 这里配置了全局的配置密码,jasypt会自动加盐,不用配置盐值。
config.setPassword(SALT_PASSWORD);
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;
}
}
这里需要注意的是:3.0.0以后的jasypt版本,加密算法需要配置成PBEWithHMACSHA512AndAES_256,其默认的加解密类是AES256TextEncryptor。IvGeneratorClassName可以设置成RandomIvGenerator。
1.x和2.x.x的jasypt版本默认的加密算法是PBEWithMD5AndDES,其默认加密类是:BasicTextEncryptor。IvGeneratorClassName需要设置成NoIvGenerator。
我这里使用的是3.0.4版本,spring-boot依赖为2.5.4。
代码语言:java复制<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.4</version>
</dependency>
3、生成密文
这里还有一个问题就是密码的密文怎么生成,可以使用测试类,也可以提供一个rest接口。方法比较简单。
代码语言:java复制@SuppressWarnings("RegexpSinglelineJava")
public final class JasyptUtil {
private JasyptUtil() {
}
public static String encrypt(String configPassword, String targetString) {
AES256TextEncryptor encryptor = new AES256TextEncryptor();
encryptor.setPassword(configPassword);
return encryptor.encrypt(targetString);
}
public static String decrypt(String configPassword, String targetString) {
AES256TextEncryptor encryptor = new AES256TextEncryptor();
encryptor.setPassword(configPassword);
return encryptor.decrypt(targetString);
}
/**
* 配置文件的密码生成和测试.
* @param args unused
*/
public static void main(String[] args) {
String configPassword = "a57fc561-e051-4e5a-abea-1c4c530cfe44";
String realPassword = "fitview.1";
// 进行加密操作
String encryptPassword = encrypt(configPassword, realPassword);
// 进行解密操作
String decryptPassword = decrypt(configPassword, encryptPassword);
// 输出明文和密文
System.out.println("encryptPassword=" encryptPassword);
System.out.println("decryptPassword=" decryptPassword);
}
}
上面是3.0.x的写法,2.0.0以下的写法:把AES256TextEncryptor换成BasicTextEncryptor即可。这个取决于你在config类里面设置的加密算法。
(PBEWithHMACSHA512AndAES_256 对应 AES256TextEncryptor )
(PBEWithMD5AndDES 对应 BasicTextEncryptor)
当然,你也可以自己实现TextEncryptor定义你自己的加密算法。