Spring Boot2.X 配置文件自动解密读取

Posted 福州-司马懿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Boot2.X 配置文件自动解密读取相关的知识,希望对你有一定的参考价值。

第三方库 jasypt

要实现该功能,我们要借助一个 Github 的第三方库 com.github.ulisesbocchio » jasypt-spring-boot-starter,Github地址为 https://github.com/ulisesbocchio/jasypt-spring-boot

Maven 地址如下:https://mvnrepository.com/artifact/com.github.ulisesbocchio/jasypt-spring-boot-starter
点击最新的版本号,会列出 maven 或 gradle 的依赖方式,拷贝即可

maven 的依赖方式

<!-- https://mvnrepository.com/artifact/com.github.ulisesbocchio/jasypt-spring-boot-starter -->
<dependency>
    <groupId>com.github.ulisesbocchio</groupId>
    <artifactId>jasypt-spring-boot-starter</artifactId>
    <version>2.1.2</version>
</dependency>

gradle 的依赖方式

// https://mvnrepository.com/artifact/com.github.ulisesbocchio/jasypt-spring-boot-starter
compile group: 'com.github.ulisesbocchio', name: 'jasypt-spring-boot-starter', version: '2.1.2'

jasypt 官网

http://www.jasypt.org/cli.html,可以查到它所支持的摘要算法和加密方式

摘要算法

  • MD2
  • MD5
  • SHA
  • SHA-256
  • SHA-384
  • SHA-512

加密方式

  • PBEWITHMD5ANDDES
  • PBEWITHMD5ANDTRIPLEDES
  • PBEWITHSHA1ANDDESEDE
  • PBEWITHSHA1ANDRC2_40

jsypt 的仓库路径

在 maven 中添加引用之后,jsypt 会自动被下载到 m2 仓库中,默认的地址为 C:\\Users\\【用户名】.m2\\repository\\org\\jasypt\\jasypt\\1.9.3

命令行加密数据

java -cp 与 java -jar 的区别

  • java -cp 和 -classpath 一样,是指定类运行所依赖其他类的路径,通常是类库,jar包之类
  • java -jar 执行的适合,会用到 jar 包里面的 META-INF\\MANIFEST.MF 文件,在该文件中,有一个叫Main-Class的参数,它说明了java -jar命令执行的类
cd C:\\Users\\【用户名】\\.m2\\repository\\org\\jasypt\\jasypt\\1.9.3

java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI input=【待加密的数据】 password=【密码】algorithm=PBEWithMD5AndDES

实现自动解密

默认属性加密

创建包含加密数据的 yaml 文件

在 resources 的 config 目录下创建一个 encrypt.xml 文件(文件名随意),内容如下

spring:
 datasource:
  url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=mydatabase
  username: bob
  password: ENC(eGm+abBtq2NXGt7FZ3SDoEPpHaQ2OOpXZ/L16aSfBMc=)

ENC() 表示 括号内部的内容是加密的,spring boot 在初始化时会自动将其解密(括号内的内容用的就是我们之前通过命令行加密后的值)

启用加密配置文件

  • @EnableEncryptableProperties 表示启用加密配置文件
  • @EncryptablePropertySource 用来设置加密配置文件的路径
  • @EncryptablePropertySources 如果有多个加密配置文件,则用花括号括起来,中间用逗号隔开每一个@EncryptablePropertySource

注意:只要有用到加密配置文件,前两者都不能省

@EnableEncryptableProperties
//@EncryptablePropertySource("classpath:/config/encrypt.yml")
@EncryptablePropertySource(value="classpath:/config/encrypt.yml")
//@EncryptablePropertySources(@EncryptablePropertySource("classpath:/config/encrypt.yml"))
public class EncryptionPropertyConfig  …… 

添加一个配置类,对加密器进行配置

@Configuration
@EnableEncryptableProperties
@EncryptablePropertySource("classpath:/config/encrypt.yml")
public class EncryptionPropertyConfig 
	//这个bean的名字也不能随意更改,否则编译不过
	@Bean("jasyptStringEncryptor")
    public StringEncryptor stringEncryptor() 
		//集中式PBE字符串加密器
        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
        //简单字符串形式的PBC配置
        SimpleStringPBEConfig config = new SimpleStringPBEConfig();
        //设置加密密码(大小写敏感),密码错误将导致程序异常
        config.setPassword("YourPassword");
        //设置加密算法
        config.setAlgorithm("PBEWithMD5AndDES");
        //设置获取加密密钥的哈希迭代次数
        config.setKeyObtentionIterations("1000");
        //设置线程池大小
        config.setPoolSize("1");
        //设置加密器的提供者
        config.setProviderName("SunJCE");
        //设置加盐的类名
        config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
        //设置初始向量IV生成器的类名
        config.setIvGeneratorClassName("org.jasypt.iv.NoIvGenerator");
        //设置字节数组以base64格式输出
        config.setStringOutputType("base64");
        //将对应的配置设置到密码器上
        encryptor.setConfig(config);
        return encryptor;
    

添加一个访问控制器,当访问某个地址时,打印该变量

@RestController
public class TestController 
	@Value("$spring.datasource.password")
	private String password;

	@GetMapping("/testValue")
	public String testValue() 
		System.out.println(password);
		return "";
	

改变加密标志前缀和后缀

默认的加密前缀是 “ENC(” ,后缀是")"。但有的时候我们需要自定义,方法是在 application.yml 后面添加一段

jasypt:
 encryptor:
  property:
   prefix: "ENC@["
   suffix: "]"

这样,加密前缀就改为了 “ENC@[”,而后缀就改为了 “]”,修改配置文件后重启即可生效

spring:
 datasource:
  url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=mydatabase
  username: bob
  password: ENC@[eGm+abBtq2NXGt7FZ3SDoEPpHaQ2OOpXZ/L16aSfBMc=]

自定义属性解密方式

@Configuration
@EnableEncryptableProperties
@EncryptablePropertySource("classpath:/config/encrypt.yml")
public class EncryptionPropertyConfig 
	// 加密属性前缀
	private static final String PREFIX = "ENC@[";
	// 密钥
	private static String PASSWORD = "YourPassword";

	//同样名字不能随意修改,否则编译不通过
	@Bean(name = "encryptablePropertyResolver")
	public EncryptablePropertyResolver encryptablePropertyResolver() 
		return new MyEncryptablePropertyResolver(PREFIX, PASSWORD);
	

	private static class MyEncryptablePropertyResolver implements EncryptablePropertyResolver 

		private final String prefix;
		//PBE字符串加密器
		private final PooledPBEStringEncryptor encryptor;

		public MyEncryptablePropertyResolver(String prefix, String password) 
			this.prefix = prefix;
			// 集中式PBE字符串加密器
			encryptor = new PooledPBEStringEncryptor();
			// 简单字符串形式的PBC配置
			SimpleStringPBEConfig config = new SimpleStringPBEConfig();
			// 设置加密密码(大小写敏感),密码错误将导致程序异常
			config.setPassword("YourPassword");
			// 设置加密算法
			config.setAlgorithm("PBEWithMD5AndDES");
			// 设置获取加密密钥的哈希迭代次数
			config.setKeyObtentionIterations("1000");
			// 设置线程池大小
			config.setPoolSize("1");
			// 设置加密器的提供者
			config.setProviderName("SunJCE");
			// 设置加盐的类名
			config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
			// 设置初始向量IV生成器的类名
			config.setIvGeneratorClassName("org.jasypt.iv.NoIvGenerator");
			// 设置字节数组以base64格式输出
			config.setStringOutputType("base64");
			// 将对应的配置设置到密码器上
			encryptor.setConfig(config);
		

		/**
		依次解析每个属性的值。判断是否是加密字段,如果是则进行解密
		解密函数可以用 jsypt 自带的解密方式,也可以用自己写的一套加解密规则
		*/
		@Override
		public String resolvePropertyValue(String value) 
			System.out.println("resolvePropertyValue : " + value);
			if (!StringUtils.isEmpty(value) && value.startsWith(prefix)) 
				String encValue = value.substring(prefix.length());
				String rawValue = encryptor.decrypt(value.substring(prefix.length()));
				return rawValue;
			
			return value;
		
	

从结果可以看出,调用 resolvePropertyValue 函数之后,会对返回值和参数进行比较,如果两者不同还会再调用一次 resolvePropertyValue ,也就是说,加密支持递归加密。

以上是关于Spring Boot2.X 配置文件自动解密读取的主要内容,如果未能解决你的问题,请参考以下文章

最全Spring Boot2.x系列Config配置集成篇-1参数配置

spring boot2.x和activiti如何配置

Spring Boot2.X 自定义Redis的cacheManager,保存Json格式到Redis

Spring Boot2.x 的Druid连接池配置[附带监控]

Spring Cloud Config 配置中心 自动加解密功能

spring boot2.x发送邮件