SpringBoot:配置Jasypt加密yml配置文件属性
前言
数据安全问题频出,公司开始对数据安全进行严加管控,其中代码开发配置文件中的敏感信息不能明文存放必须密文处理,所以特此记录下Jasypt加解密方式。


框架环境
博主自己框架的版本信息
<!-- SpringBoot版本 -->
<spring-boot.version>3.2.8</spring-boot.version>
<!-- SpringCloud版本 -->
<spring-cloud.version>2023.0.3</spring-cloud.version>
<!-- SpringCloud-Alibaba版本 -->
<spring-cloud-alibaba.version>2023.0.1.0</spring-cloud-alibaba.version>
<!-- Spring Ai 人工智能框架版本 -->
<spring-ai.version>1.0.0</spring-ai.version>
<!-- bootstrap.yml加载版本 -->
<bootstrap.version>3.1.0</bootstrap.version>
Jasypt依赖
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.5</version> <!-- Spring Boot 2.x:推荐 Jasypt 2.1.x 或 3.0.x。 Spring Boot 3.x:推荐 Jasypt 3.0.5 或更高版本。 -->
</dependency>
重点:因为博主框架使用SaToken做鉴权,Gateway内就需要引用SaToken做鉴权过滤,但SaToken需要连接redis,而redis密码使用Jasypt作加密需要解密,最后Gateway(WebFlux)与Jasypt(Servlet)响应式环境冲突,导致启动失败。有相同问题的可以看这篇文章:https://www.cnblogs.com/nhdlb/p/19542319
配置类初始化Jasypt
网上使用yml配置文件加载Jasypt并通过java -jar命令传递密码的方式较多,博主这里使用的是配置类加载Jasypt,后续使用jar加密后就看不到了,如果使用命令行传递(java -Djasypt.encryptor.password=xxxxxx -jar xxx.jar )并用docker部署的话还是会将密码暴露出来。这里只是多一层考虑,大家根据自己实际情况来评估怎么使用。
import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* Jasypt配置文件加密密文
* @author zy
*/
@Configuration
public class JasyptConfig {
private static final String password = "JGk3d8r";
// 冲突:因Gateway内引用SaToken做鉴权,但SaToken需要连接redis,而redis密码使用Jasypt作加密需要解密,最后Gateway(WebFlux)与Jasypt(Servlet)响应式环境冲突,导致启动失败
// 自定义加密器, 封装在代码内,不暴露出去
@Bean("jasyptStringEncryptor")
public StringEncryptor jasyptStringEncryptor() {
PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
SimpleStringPBEConfig config = new SimpleStringPBEConfig();
// 配置文件加密的密码,写死;后续使用jar加密就可以了
//config.setPassword(password);
// 也可以使用命令行传递密码, java -Djasypt.encryptor.password=mypassword -jar xxxxx.jar
config.setPassword(System.getProperty("jasypt.encryptor.password"));
// 指定加密方式 可以查看JasyptUtil工具类有哪些加密方式
config.setAlgorithm(JasyptUtil.PBE_WITHHMACSHA_512_ANDAES_256);
// 设置密钥派生过程中的迭代次数。迭代次数越高,暴力破解成本越高
// 1000 是较保守的值,现代推荐至少 10,000~100,000(如 Spring Security 默认 PBKDF2 用 185,000)
config.setKeyObtentionIterations("100000");
// 设置加密器池的大小,"1" 表示只使用一个实例(适用于低并发或单线程场景)
config.setPoolSize("1");
// 指定 Java 加密服务提供者(Security Provider)。"SunJCE" 是 Oracle JDK 自带的默认加密提供者,支持大多数标准算法
config.setProviderName("SunJCE");
// 指定盐值(Salt)生成器类
// Salt 是随机数据,用于防止彩虹表攻击。每次加密都会生成不同的 salt,即使明文相同,密文也不同。
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
// 设置加密后输出的字符串编码格式
config.setStringOutputType("base64");
// 不需要 IV 的算法,org.jasypt.iv.NoIvGenerator
// 使用 CBC、GCM 等需要 IV 的模式 时(例如 AES/CBC),就必须提供 IV 生成器 org.jasypt.iv.RandomIvGenerator
config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");
encryptor.setConfig(config);
return encryptor;
}
}
Jasypt工具类
用于生成密文与解密密文的工具类
import com.higentec.common.utils.spring.SpringUtils;
import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.EnvironmentPBEConfig;
public class JasyptUtil {
/**
* PBE 算法
*/
public static final String PBE_ALGORITHMS_MD5_DES = "PBEWITHMD5ANDDES";
public static final String PBE_ALGORITHMS_MD5_TRIPLEDES = "PBEWITHMD5ANDTRIPLEDES";
public static final String PBE_ALGORITHMS_SHA1_DESEDE = "PBEWITHSHA1ANDDESEDE";
public static final String PBE_ALGORITHMS_SHA1_RC2_40 = "PBEWITHSHA1ANDRC2_40";
public static final String PBE_WITHHMACSHA_512_ANDAES_256 = "PBEWITHHMACSHA512ANDAES_256";
public static final String PBE_WITHHMACSHA_256_ANDAES_256 = "PBEWITHHMACSHA256ANDAES_256";
public static final String PBE_WithMD5AndTripleDES = "PBEWithMD5AndTripleDES";
public static final String PBE_WithHmacSHA_1_AndAES_128 = "PBEWithHmacSHA1AndAES_128";
public static final String PBE_WithHmacSHA_256_AndAES_128 = "PBEWithHmacSHA256AndAES_128";
private JasyptUtil() {
}
/**
* Jasypt 加密
*
* @param encryptedStr 加密字符串
* @param password 盐值
* @return
*/
public static String encrypt(String encryptedStr, String password) {
return encrypt(encryptedStr, PBE_WITHHMACSHA_512_ANDAES_256, password);
}
/**
* Jasypt 加密
*
* @param encryptedStr 加密字符串
* @param algorithm 加密算法
* PBE ALGORITHMS: [PBEWITHMD5ANDDES, PBEWITHMD5ANDTRIPLEDES, PBEWITHSHA1ANDDESEDE, PBEWITHSHA1ANDRC2_40]
* @param password 盐值
* @return
*/
public static String encrypt(String encryptedStr, String algorithm, String password) {
// StandardPBEStringEncryptor、StandardPBEBigDecimalEncryptor、StandardPBEBigIntegerEncryptor、StandardPBEByteEncryptor
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
EnvironmentPBEConfig config = new EnvironmentPBEConfig();
// 指定加密方式 可以查看JasyptUtil工具类有哪些加密方式
config.setAlgorithm(algorithm);
// 配置文件加密的密码
config.setPassword(password);
// 设置密钥派生过程中的迭代次数。迭代次数越高,暴力破解成本越高
// 1000 是较保守的值,现代推荐至少 10,000~100,000(如 Spring Security 默认 PBKDF2 用 185,000)
config.setKeyObtentionIterations("100000");
// 设置加密器池的大小,"1" 表示只使用一个实例(适用于低并发或单线程场景)
config.setPoolSize("1");
// 指定 Java 加密服务提供者(Security Provider)。"SunJCE" 是 Oracle JDK 自带的默认加密提供者,支持大多数标准算法
config.setProviderName("SunJCE");
// 指定盐值(Salt)生成器类
// Salt 是随机数据,用于防止彩虹表攻击。每次加密都会生成不同的 salt,即使明文相同,密文也不同。
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
// 不需要 IV 的算法,org.jasypt.iv.NoIvGenerator
// 使用 CBC、GCM 等需要 IV 的模式 时(例如 AES/CBC),就必须提供 IV 生成器 org.jasypt.iv.RandomIvGenerator
config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");
encryptor.setConfig(config);
// 加密
return encryptor.encrypt(encryptedStr);
}
/**
* Jasypt 解密
*
* @param decryptStr 解密字符串
* @param password 盐值
* @return
*/
public static String decrypt(String decryptStr, String password) {
return decrypt(decryptStr, PBE_WITHHMACSHA_512_ANDAES_256, password);
}
/**
* Jasypt 解密
*
* @param decryptStr 解密字符串
* @param algorithm 指定解密算法:解密算法要与加密算法一一对应
* PBE ALGORITHMS: [PBEWITHMD5ANDDES, PBEWITHMD5ANDTRIPLEDES, PBEWITHSHA1ANDDESEDE, PBEWITHSHA1ANDRC2_40]
* @param password 盐值
* @return
*/
public static String decrypt(String decryptStr, String algorithm, String password) {
// StandardPBEStringEncryptor、StandardPBEBigDecimalEncryptor、StandardPBEBigIntegerEncryptor、StandardPBEByteEncryptor
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
EnvironmentPBEConfig config = new EnvironmentPBEConfig();
// 指定加密方式 可以查看JasyptUtil工具类有哪些加密方式
config.setAlgorithm(algorithm);
// 配置文件加密的密码
config.setPassword(password);
// 设置密钥派生过程中的迭代次数。迭代次数越高,暴力破解成本越高
// 1000 是较保守的值,现代推荐至少 10,000~100,000(如 Spring Security 默认 PBKDF2 用 185,000)
config.setKeyObtentionIterations("100000");
// 设置加密器池的大小,"1" 表示只使用一个实例(适用于低并发或单线程场景)
config.setPoolSize("1");
// 指定 Java 加密服务提供者(Security Provider)。"SunJCE" 是 Oracle JDK 自带的默认加密提供者,支持大多数标准算法
config.setProviderName("SunJCE");
// 指定盐值(Salt)生成器类
// Salt 是随机数据,用于防止彩虹表攻击。每次加密都会生成不同的 salt,即使明文相同,密文也不同。
config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
// 不需要 IV 的算法,org.jasypt.iv.NoIvGenerator
// 使用 CBC、GCM 等需要 IV 的模式 时(例如 AES/CBC),就必须提供 IV 生成器 org.jasypt.iv.RandomIvGenerator
config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");
encryptor.setConfig(config);
// 解密
return encryptor.decrypt(decryptStr);
}
/**
* 使用自定义加密器进行加密
* @param str 需要进行加密的字符串
*/
public static String encrypt_customize(String str){
StringEncryptor encryptor = SpringUtils.getBean("jasyptStringEncryptor", StringEncryptor.class);
return encryptor.encrypt(str);
}
/**
* 使用自定义加密器进行解密
* @param str 需要进行解密的密文
*/
public static String decrypt_customize(String str){
StringEncryptor encryptor = SpringUtils.getBean("jasyptStringEncryptor", StringEncryptor.class);
return encryptor.decrypt(str);
}
// public static void main(String[] args) {
// String encryptedStr = "12345678ab";
// String algorithm = PBE_WITHHMACSHA_512_ANDAES_256;
// String password = "y0BwPTcN";
// String str = JasyptUtil.encrypt(encryptedStr, algorithm, password);
// System.out.println("加密后的字符串:" + str);
// System.out.println("解密后的字符串:" + JasyptUtil.decrypt(str, algorithm, password));
// }
}
yml配置文件
# Spring
spring:
application:
# 应用名称
name: base-system
profiles:
#环境配置
active: @profiles.active@
# 冲突:因Gateway内引用SaToken做鉴权,但SaToken需要连接redis,而redis密码使用Jasypt作加密需要解密,最后Gateway(WebFlux)与Jasypt(Servlet)响应式环境冲突,导致启动失败
# 手动优先加载 Jasypt 配置文件解密Bean实体
cloud:
bootstrap:
# 多个可以使用,号分隔
sources: com.higentec.common.config.JasyptConfig
# Jasypt配置文件解密
jasypt:
encryptor:
# 引用手动优先加载的解密Bean
bean: jasyptStringEncryptor

重点: 使用加密后的密文需要用 ENC(密文) 包裹起来,如此Jasypt才能识别哪些需要解密。

-----------------------------------
作者:怒吼的萝卜
链接:http://www.cnblogs.com/nhdlb/
-----------------------------------

浙公网安备 33010602011771号