Spring Boot 项目的配置加密:使用 Jasypt
Java 8
Spring Boot 2.7.3
Jasypt Spring Boot Starter 3.0.5 (jsypt 1.9.3)
IDE:Eclipse Version: 2022-09
--
序章
Jasypt 官网:
Jasypt 代码库:
https://github.com/jasypt/jasypt
About 信息:
About
Jasypt (Java Simplified Encryption) is a java library which allows the
developer to add basic encryption capabilities to his/her projects with
minimum effort, and without the need of having deep knowledge on how
cryptography works.
Jasypt Spring Boot Starter 版本信息:给 Spring Boot 集成用
添加依赖包:
<!-- https://mvnrepository.com/artifact/com.github.ulisesbocchio/jasypt-spring-boot-starter -->
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
项目版本信息 及 包依赖:
注意,Jasypt Spring Boot Starter 3.0.5 需要和 之前的版本的加密方式做区分。
使用 jasypt 后的 Bean
启动项目,检查 相关 Bean:
搜索 jas:
Line 122: com.ulisesbocchio.jasyptspringboot.configuration.EncryptablePropertyResolverConfiguration
Line 125: lazyJasyptStringEncryptor
Line 130: com.ulisesbocchio.jasyptspringboot.configuration.CachingConfiguration
Line 132: com.ulisesbocchio.jasyptspringboot.configuration.EnableEncryptablePropertiesConfiguration
Line 134: com.ulisesbocchio.jasyptspringbootstarter.JasyptSpringBootAutoConfiguration
Line 134: com.ulisesbocchio.jasyptspringbootstarter.JasyptSpringBootAutoConfiguration 同上 jas出现了两次
搜索 crypt:
Line 122: com.ulisesbocchio.jasyptspringboot.configuration.EncryptablePropertyResolverConfiguration
Line 123: encryptablePropertySourceConverter
Line 125: lazyJasyptStringEncryptor
Line 126: lazyEncryptablePropertyDetector
Line 128: lazyEncryptablePropertyFilter
Line 129: lazyEncryptablePropertyResolver
Line 132: com.ulisesbocchio.jasyptspringboot.configuration.EnableEncryptablePropertiesConfiguration
Line 133: enableEncryptablePropertySourcesPostProcessor
测试加密、解密:main方法
本地运行。ben发布于博客园
使用 StandardPBEStringEncryptor 执行:使用了一个 盐值。
public static void main(String[] args) {
// 盐值
String salt = "999999";
String mingWen = "12345 badfsd 千山万水";
testJiaMi(salt, mingWen);
testJiaMi(salt, "mypwd123456");
testJiaMi(salt, "13344445555");
}
private static void testJiaMi(String salt, String mingWen) {
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
encryptor.setPassword(salt);
System.out.println(encryptor + ", " + encryptor.isInitialized());
System.out.println("测试结果:\r\nmingWen = " + mingWen + ", lenth=" + mingWen.length());
String miWen = encryptor.encrypt(mingWen);
System.out.println(" miWen = " + miWen);
String deMiWen = encryptor.decrypt(miWen);
System.out.println("deMiWen = " + deMiWen + ", lenth=" + deMiWen.length());
System.out.println(encryptor + ", " + encryptor.isInitialized());
System.out.println();
}
测试结果:成功。ben发布于博客园
org.jasypt.encryption.pbe.StandardPBEStringEncryptor@23ab930d, false
测试结果:
mingWen = 12345 badfsd 千山万水, lenth=17
miWen = CX5146xzuR07LFTAEOaqMtIcfifrgZ0TzgdJUahzYZKpjnzKV3T27A==
deMiWen = 12345 badfsd 千山万水, lenth=17
org.jasypt.encryption.pbe.StandardPBEStringEncryptor@23ab930d, true
org.jasypt.encryption.pbe.StandardPBEStringEncryptor@475530b9, false
测试结果:
mingWen = mypwd123456, lenth=11
miWen = UdRaipUB9z0HYXtNGCDC9RF5GVcJplEG
deMiWen = mypwd123456, lenth=11
org.jasypt.encryption.pbe.StandardPBEStringEncryptor@475530b9, true
org.jasypt.encryption.pbe.StandardPBEStringEncryptor@1d057a39, false
测试结果:
mingWen = 13344445555, lenth=11
miWen = SlOftyHgNu2HCrDkElV1HOJxdKFX0+hF
deMiWen = 13344445555, lenth=11
org.jasypt.encryption.pbe.StandardPBEStringEncryptor@1d057a39, true
再次执行:盐值 不变,但 密文变了。
org.jasypt.encryption.pbe.StandardPBEStringEncryptor@23ab930d, false
测试结果:
mingWen = 12345 badfsd 千山万水, lenth=17
miWen = MqtefEd8Rw5yKt871WHL2YXu1ZUeS6beasVv1e+LGpVX/LDD7GyIjA==
deMiWen = 12345 badfsd 千山万水, lenth=17
org.jasypt.encryption.pbe.StandardPBEStringEncryptor@23ab930d, true
org.jasypt.encryption.pbe.StandardPBEStringEncryptor@475530b9, false
测试结果:
mingWen = mypwd123456, lenth=11
miWen = bZouQQwsrZpsA3IxlWSaEre8web0vvn8
deMiWen = mypwd123456, lenth=11
org.jasypt.encryption.pbe.StandardPBEStringEncryptor@475530b9, true
org.jasypt.encryption.pbe.StandardPBEStringEncryptor@1d057a39, false
测试结果:
mingWen = 13344445555, lenth=11
miWen = Zobj74KzPHO27b8RlynLosHrrVBzTbLQ
deMiWen = 13344445555, lenth=11
org.jasypt.encryption.pbe.StandardPBEStringEncryptor@1d057a39, true
什么是 StandardPBEStringEncryptor?
拷贝自 类的注释:
* <p>
* Standard implementation of the {@link PBEStringEncryptor} interface.
* This class lets the user specify the algorithm (and provider) to be used for
* encryption, the password to use,
* the number of hashing iterations and the salt generator
* that will be applied for obtaining
* the encryption key.
* </p>
类定义:
package org.jasypt.encryption.pbe;
public final class StandardPBEStringEncryptor implements PBEStringCleanablePasswordEncryptor {
// 两个构造函数
/**
* Creates a new instance of <tt>StandardPBEStringEncryptor</tt>.
*/
public StandardPBEStringEncryptor() {
super();
this.byteEncryptor = new StandardPBEByteEncryptor();
this.base64 = new Base64();
}
/*
* Creates a new instance of <tt>StandardPBEStringEncryptor</tt> using
* the specified byte encryptor (constructor used for cloning)
*/
private StandardPBEStringEncryptor(final StandardPBEByteEncryptor standardPBEByteEncryptor) {
super();
this.byteEncryptor = standardPBEByteEncryptor;
this.base64 = new Base64();
}
}
加密 Spring Boot 项目中配置文件的值
测试的配置文件:ben发布于博客园
app:
# 明文版
ming:
pwd: mypwd123456
phone: 13344445555
# 密文版
mi:
pwd2: ENC(IwyG8h8pWvzYdoAKJf1yrlQDl8lP8NHy)
phone2: ENC(2dMUTBdi65iyPFNEWJNhq3y6Uhj0gIsb)
测试代码:TestRunner.java
@Component
@Slf4j
public class TestRunner implements ApplicationRunner {
// 明文配置
@Value("${app.ming.pwd}")
private String pwd;
@Value("${app.ming.phone}")
private String phone;
// 密文配置
@Value("${app.mi.pwd2}")
private String pwd2;
@Value("${app.mi.phone2}")
private String phone2;
@Override
public void run(ApplicationArguments args) throws Exception {
log.info("启动 TestRunner...");
print(pwd);
print(phone);
print(pwd2);
print(phone2);
}
private void print(String str) {
System.out.println("str = " + str + ", length = " + str.length() + "!");
}
}
启动项目:发生错误。ben发布于博客园
Application run failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testRunner': Injection of autowired dependencies failed; nested exception is java.lang.IllegalStateException: either 'jasypt.encryptor.password', one of ['jasypt.encryptor.private-key-string', 'jasypt.encryptor.private-key-location'] for asymmetric encryption, or one of ['jasypt.encryptor.gcm-secret-key-string', 'jasypt.encryptor.gcm-secret-key-location', 'jasypt.encryptor.gcm-secret-key-password'] for AES/GCM encryption must be provided for Password-based or Asymmetric encryption AutowiredAnnotationBeanPostProcessor.java:405) ~[spring-beans-5.3.22.jar:5.3.22] |
缺少配置了。
添加配置 jasypt.encryptor.password :ben发布于博客园
jasypt:
encryptor:
password: 999999
启动项目:又出错了
Application run failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testRunner': Injection of autowired dependencies failed; nested exception is com.ulisesbocchio.jasyptspringboot.exception.DecryptionException: Unable to decrypt property: ENC(IwyG8h8pWvzYdoAKJf1yrlQDl8lP8NHy) resolved to: ENC(IwyG8h8pWvzYdoAKJf1yrlQDl8lP8NHy). Decryption of Properties failed, make sure encryption/decryption passwords match |
这应该和 使用的 Encryptor 有关。
默认使用的是 lazyJasyptStringEncryptor,而测试使用的是 StandardPBEStringEncryptor 对象。ben发布于博客园
详情如下:
lazyJasyptStringEncryptor
bean=
com.ulisesbocchio.jasyptspringboot.encryptor.DefaultLazyEncryptor@149f5761
class com.ulisesbocchio.jasyptspringboot.encryptor.DefaultLazyEncryptor
来源:https://github.com/ulisesbocchio/jasypt-spring-boot
由于使用的加密算法不同,该为使用 默认的 lazyJasyptStringEncryptor (class com.ulisesbocchio.jasyptspringboot.encryptor.DefaultLazyEncryptor) 来加密得到字符串:
@Autowired
private DefaultLazyEncryptor lazyJasyptStringEncryptor;
print(lazyJasyptStringEncryptor.encrypt("mypwd123456")); // iMdrE/nYSuClCUv942aBdcd+NU8lA3vToVIVnjbOLCc=
print(lazyJasyptStringEncryptor.encrypt("13344445555")); // lZr2cBej3rl3PuB3x4S2eH9dq1EMXw1T9vd4FgV4VcM=
修改配置后启动:ben发布于博客园
# 必须:生成 密文时;解密密文时。
jasypt:
encryptor:
algorithm: PBEWithMD5AndDES
password: 999999
app:
ming:
pwd: mypwd123456
phone: 13344445555
mi:
pwd2: ENC(iMdrE/nYSuClCUv942aBdcd+NU8lA3vToVIVnjbOLCc=)
phone2: ENC(lZr2cBej3rl3PuB3x4S2eH9dq1EMXw1T9vd4FgV4VcM=)
启动成功:获取到了 解密后的明文
启动 TestRunner...
str = mypwd123456, length = 11!
str = 13344445555, length = 11!
str = mypwd123456, length = 11!
str = 13344445555, length = 11!
检查 DefaultLazyEncryptor 的关系
public class DefaultLazyEncryptor implements StringEncryptor {
}
// 接口
public interface StringEncryptor {
}
和 StandardPBEStringEncryptor 的关系:都是 StringEncryptor 的 实现类。
public final class StandardPBEStringEncryptor implements PBEStringCleanablePasswordEncryptor {
}
public interface PBEStringCleanablePasswordEncryptor extends PBEStringEncryptor, CleanablePasswordBased {
}
public interface PBEStringEncryptor extends StringEncryptor, PasswordBased {
}
public interface PasswordBased {
}
定制 Encryptor
参考:
https://github.com/ulisesbocchio/jasypt-spring-boot
其中的“Use you own Custom Encryptor”。ben发布于博客园
自测 使用 StandardPBEStringEncryptor 进行加解密。
添加 名为 jasyptStringEncryptor 的 Bean:
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean("jasyptStringEncryptor")
public StandardPBEStringEncryptor jasyptStringEncryptor() {
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
EnvironmentStringPBEConfig pconf = new EnvironmentStringPBEConfig();
pconf.setAlgorithm("PBEWithMD5AndDES");
pconf.setPassword("pwd111222aaa");
encryptor.setConfig(pconf);
return encryptor;
}
}
添加工具类:ben发布于博客园
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig;
public final class StandardPBEStringEncryptorUtils {
private static StandardPBEStringEncryptor encryptor;
static {
encryptor = new StandardPBEStringEncryptor();
EnvironmentStringPBEConfig pconf = new EnvironmentStringPBEConfig();
pconf.setAlgorithm("PBEWithMD5AndDES");
pconf.setPassword("pwd111222aaa");
encryptor.setConfig(pconf);
}
public static String encrypt(String mingWen) {
return encryptor.encrypt(mingWen);
}
public static String decrypt(String miWen) {
return encryptor.decrypt(miWen);
}
}
将需要加密的配置 加密:
app:
ming:
pwd: mypwd123456
phone: 13344445555
mi:
pwd2: ENC(hv/WdQoiV5SbdtQbF8Lpuz06NUQbpPpN)
phone2: ENC(lohQ0/L9YgPppIwUHrDC2ddgllWN24Uh)
启动项目,测试:成功。ben发布于博客园
启动 TestRunner...
str = mypwd123456, length = 11!
str = 13344445555, length = 11!
str = mypwd123456, length = 11!
str = 13344445555, length = 11!
检查 启动后的Bean,发现 存在两个 StringEncryptor:
jasyptStringEncryptor
bean=
org.jasypt.encryption.pbe.StandardPBEStringEncryptor@37d00a23
class org.jasypt.encryption.pbe.StandardPBEStringEncryptor
lazyJasyptStringEncryptor
bean=
com.ulisesbocchio.jasyptspringboot.encryptor.DefaultLazyEncryptor@39651a82
class com.ulisesbocchio.jasyptspringboot.encryptor.DefaultLazyEncryptor
另外的好消息:
使用 定制的 StandardPBEStringEncryptor 时,不需要配置 jasypt.encryptor.* 了。
进一步探索:
非对称加密、EncryptionOperationNotPossibleException 异常 的处理(使用 jasypt.encryptor.algorithm = PBEWITHHMACSHA512ANDAES_256 时。)
---END---ben发布于博客园
本文链接:
https://www.cnblogs.com/luo630/p/17154027.html
ben发布于博客园
参考资料
1、jasypt-spring-boot
https://github.com/ulisesbocchio/jasypt-spring-boot
2、Spring Boot 配置文件密码加密两种方案
https://www.cnblogs.com/kexianting/p/11689289.html
3、使用jasypt 进行数据库配置加密
https://blog.csdn.net/YISHENGYOUNI95/article/details/127518089
4、Jasypt加解密
by i笨笨i
已于 2022-11-11 12:11:00 修改
原文链接:https://blog.csdn.net/C_Karen/article/details/127803058
5、springboot的 加密依赖 导致的 出现异常EncryptionOperationNotPossibleException
by qq_43472248
于 2021-08-06 12:38:34 发布
原文链接:https://blog.csdn.net/qq_43472248/article/details/119451546
6、
ben发布于博客园