一、场景描述
在项目开发过程中,我们往往可以看到许多项目的配置文件中可以看到各种明文密码的情况,比如:数据库密码、Redis
连接密码等等一些敏感信息就这么赤裸裸的暴露在配置文件中,如果这些配置信息被图谋不轨的人拿到,那损失和后果就不堪设想。
之前倒是看到过一个例子,一个程序员把自己公司的项目代码上传到了自己的GitHub仓库里了,结果配置文件忘了处理,导致公司数据库泄露,关键问题是,这个公司还是个酒店管理公司,因此后果可想而知了(又要拆散多少对“恩爱”的夫妻)…
换个角度想,假如当时那个项目的配置文件里,所有重要信息都经过了加密,那这一幕大概率就不会发生了。所以,即使是项目的配置文件,重要的信息也得加密。
二、解决方案
三、实践操作
-
创建
Spring Boot
项目配置主启动类采用
@SpringBootApplication
配置 -
引入
jasypt-spring-boot
组件(3.x
和2.x
加密算法有变化)<!-- jasypt 配置文件敏感信息加解密 --> <dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>jasypt-spring-boot-starter</artifactId> <version>3.0.3</version> </dependency> <!-- jasypt 配置文件敏感信息加解密 --> <dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>jasypt-spring-boot-starter</artifactId> <version>2.1.2</version> </dependency>
-
在
Spring Boot
项目的配置文件中配置加解密的秘钥jasypt.encryptor.password=xxxx@2020
-
在
Spring Boot
项目的配置文件中将需要加密的配置信息采用ENC()
包裹即可# 如下加密信息如何得到,请参考 第四大点的测试用例 spring.datasource.druid.password=ENC(KvET8AadJk8Ro25LK885WFWJIjXNYiAkQVBMezUe/sJCy/XK38PP0OpDsk81XswR)
-
以上配置即可完成敏感配置信息的加密全部过程
四、测试用例
-
2.x
版本的分析-
如果引入的是
2.x
的版本,启动信息如下:String Encryptor custom Bean not found with name 'jasyptStringEncryptor'. Initializing Default String Encryptor Encryptor config not found for property jasypt.encryptor.algorithm, using default value: PBEWithMD5AndDES Encryptor config not found for property jasypt.encryptor.key-obtention-iterations, using default value: 1000 Encryptor config not found for property jasypt.encryptor.pool-size, using default value: 1 Encryptor config not found for property jasypt.encryptor.provider-name, using default value: null Encryptor config not found for property jasypt.encryptor.provider-class-name, using default value: null Encryptor config not found for property jasypt.encryptor.salt-generator-classname, using default value: org.jasypt.salt.RandomSaltGenerator Encryptor config not found for property jasypt.encryptor.iv-generator-classname, using default value: org.jasypt.iv.NoIvGenerator Encryptor config not found for property jasypt.encryptor.string-output-type, using default value: base64
-
通过以上信息的解读,我们可以了解到的信息如下:
-
默认加密算法:
PBEWithMD5AndDES
-
默认的迭代次数: 1000
-
默认池大小: 1
-
默认生成盐的类:
org.jasypt.salt.RandomSaltGenerator
-
默认
IV
生成器类:org.jasypt.iv.NoIvGenerator
-
默认输出类型:
base64
-
-
-
3.x
版本分析-
如果引入的是
3.x
的版本,启动信息如下:String Encryptor custom Bean not found with name 'jasyptStringEncryptor'. Initializing Default String Encryptor Encryptor config not found for property jasypt.encryptor.algorithm, using default value: PBEWITHHMACSHA512ANDAES_256 Encryptor config not found for property jasypt.encryptor.key-obtention-iterations, using default value: 1000 Encryptor config not found for property jasypt.encryptor.pool-size, using default value: 1 Encryptor config not found for property jasypt.encryptor.provider-name, using default value: null Encryptor config not found for property jasypt.encryptor.provider-class-name, using default value: null Encryptor config not found for property jasypt.encryptor.salt-generator-classname, using default value: org.jasypt.salt.RandomSaltGenerator Encryptor config not found for property jasypt.encryptor.iv-generator-classname, using default value: org.jasypt.iv.RandomIvGenerator Encryptor config not found for property jasypt.encryptor.string-output-type, using default value: base64
-
通过以上信息的解读,我们可以了解到的信息如下:
-
默认加密算法:
PBEWITHHMACSHA512ANDAES_256
-
默认的迭代次数: 1000
-
默认池大小: 1
-
默认生成盐的类:
org.jasypt.salt.RandomSaltGenerator
-
默认
IV
生成器类:org.jasypt.iv.RandomIvGenerator
-
默认输出类型:
base64
-
-
-
通过如上信息的获取,我们即可编写测试工具,根据不同的版本和加密算法生成敏感信息的加密密文
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor; import org.jasypt.encryption.pbe.StandardPBEStringEncryptor; import org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig; import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig; /** * @ClassName: JasypUtil * @Description: Jasyp加解密工具类 * @Author: Rambo * @CreateDate: 2020/7/13 10:12 * @UpdateUser: Rambo * @UpdateDate: 2020/7/13 10:12 * @Version: 1.0.0 */ public class JasypUtil { private static final String PBEWITHMD5ANDDES = "PBEWithMD5AndDES"; private static final String PBEWITHHMACSHA512ANDAES_256 = "PBEWITHHMACSHA512ANDAES_256"; /** * @Description: Jasyp加密(PBEWithMD5AndDES) * @Author: Rambo * @CreateDate: 2020/7/13 10:24 * @UpdateUser: Rambo * @UpdateDate: 2020/7/13 10:24 * @param plainText 待加密的原文 * @param factor 加密秘钥 * @return java.lang.String * @Version: 1.0.0 */ public static String encryptWithMD5(String plainText, String factor) { // 1. 创建加解密工具实例 StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); // 2. 加解密配置 EnvironmentStringPBEConfig config = new EnvironmentStringPBEConfig(); config.setAlgorithm(PBEWITHMD5ANDDES); config.setPassword(factor); encryptor.setConfig(config); // 3. 加密 return encryptor.encrypt(plainText); } /** * @Description: Jaspy解密(PBEWithMD5AndDES) * @Author: Rambo * @CreateDate: 2020/7/13 10:28 * @UpdateUser: Rambo * @UpdateDate: 2020/7/13 10:28 * @param encryptedText 待解密密文 * @param factor 解密秘钥 * @return java.lang.String * @Version: 1.0.0 */ public static String decryptWithMD5(String encryptedText, String factor) { // 1. 创建加解密工具实例 StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor(); // 2. 加解密配置 EnvironmentStringPBEConfig config = new EnvironmentStringPBEConfig(); config.setAlgorithm(PBEWITHMD5ANDDES); config.setPassword(factor); encryptor.setConfig(config); // 3. 解密 return encryptor.decrypt(encryptedText); } /** * @Description: Jasyp 加密(PBEWITHHMACSHA512ANDAES_256) * @Author: Rambo * @CreateDate: 2020/7/25 14:34 * @UpdateUser: Rambo * @UpdateDate: 2020/7/25 14:34 * @param plainText 待加密的原文 * @param factor 加密秘钥 * @return java.lang.String * @Version: 1.0.0 */ public static String encryptWithSHA512(String plainText, String factor) { // 1. 创建加解密工具实例 PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor(); // 2. 加解密配置 SimpleStringPBEConfig config = new SimpleStringPBEConfig(); config.setPassword(factor); config.setAlgorithm(PBEWITHHMACSHA512ANDAES_256); // 为减少配置文件的书写,以下都是 Jasyp 3.x 版本,配置文件默认配置 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); // 3. 加密 return encryptor.encrypt(plainText); } /** * @Description: Jaspy解密(PBEWITHHMACSHA512ANDAES_256) * @Author: Rambo * @CreateDate: 2020/7/25 14:40 * @UpdateUser: Rambo * @UpdateDate: 2020/7/25 14:40 * @param encryptedText 待解密密文 * @param factor 解密秘钥 * @return java.lang.String * @Version: 1.0.0 */ public static String decryptWithSHA512(String encryptedText, String factor) { // 1. 创建加解密工具实例 PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor(); // 2. 加解密配置 SimpleStringPBEConfig config = new SimpleStringPBEConfig(); config.setPassword(factor); config.setAlgorithm(PBEWITHHMACSHA512ANDAES_256); // 为减少配置文件的书写,以下都是 Jasyp 3.x 版本,配置文件默认配置 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); // 3. 解密 return encryptor.decrypt(encryptedText); } public static void main(String[] args) { String factor = "xxxx@2020"; String plainText = "123456"; String encryptWithMD5Str = encryptWithMD5(plainText, factor); String decryptWithMD5Str = decryptWithMD5(encryptWithMD5Str, factor); String encryptWithSHA512Str = encryptWithSHA512(plainText, factor); String decryptWithSHA512Str = decryptWithSHA512(encryptWithSHA512Str, factor); System.out.println("采用MD5加密前原文密文:" + encryptWithMD5Str); System.out.println("采用MD5解密后密文原文:" + decryptWithMD5Str); System.out.println(); System.out.println("采用SHA512加密前原文密文:" + encryptWithSHA512Str); System.out.println("采用SHA512解密后密文原文:" + decryptWithSHA512Str); } }