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 ,也就是说,加密支持递归加密。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值