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發佈於博客園

 

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