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 官网:

http://www.jasypt.org

 

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
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(

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发布于博客园

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章