在我们的服务中不可避免的需要使用到一些秘钥(数据库、redis等);使用过SpringBoot配置文件的朋友都知道,资源文件中的内容通常情况下是明文显示,安全性就比较低一些。打开application.properties或application.yml,比如mysql登陆密码,redis登陆密码以及第三方的密钥等等一览无余,这里介绍一个加解密组件,提高一些属性配置的安全性。
开发和测试环境还好,但生产如果采用明文配置讲会有安全问题,jasypt是一个通用的加解密库,我们可以使用它。
<dependency><groupId>com.github.ulisesbocchio</groupId><artifactId>jasypt-spring-boot-starter</artifactId><version>2.1.1</version>
</dependency>
配置文件:
# 加密的密钥
# 测试环境可以采用在配置文件中配置
# 生产环境建议采用启动参数的形式传入
# 其他配置参数参考:com.ulisesbocchio.jasyptspringboot.properties.JasyptEncryptorConfigurationProperties
jasypt.encryptor.password=you salt# 解密得到原始密码
spring.datasource.password= ENC(密文)
那密文怎么来的呢?
@Autowired
StringEncryptor stringEncryptor;@Test
public void encrypt() {System.out.println("PWD: " + stringEncryptor.encrypt("yourpassword"));
}
public static void main(String[] args) {BasicTextEncryptor textEncryptor = new BasicTextEncryptor();//加密所需的salt(盐)textEncryptor.setPassword("G0CvDz7oJn6");//要加密的数据(数据库的用户名或密码)String username = textEncryptor.encrypt("root");String password = textEncryptor.encrypt("root123");System.out.println("username:"+username);System.out.println("password:"+password);}
jasypt默认使用StringEncryptor来进行加解密,我们也可以自定义自己的加解密类来替换它。
再来详细介绍一下:
jasypt由一个国外大神写的一个springboot下的工具包。Git地址:https://github.com/ulisesbocchio/jasypt-spring-boot
直接上代码:
1、pom文件中增加依赖:
<dependency><groupId>com.github.ulisesbocchio</groupId><artifactId>jasypt-spring-boot-starter</artifactId><version>2.1.1</version>
</dependency>
2、application.yml文件中增加jasypt的秘钥(该秘钥自定义的):
jasypt:encryptor:#加密秘钥password: EbfYkitulv73I2p0mXI50JMXoaxZTKJ7
3、测试类:
@RestController
public class IndexController {@Autowiredprivate StringEncryptor encryptor;/*** 测试jasypt加密解密*/@GetMapping("/jasypt")public void testJasypt() {String password = "123456";String encryptPwd = encryptor.encrypt(password);System.out.println("加密::" + encryptPwd);System.out.println("解密:" + encryptor.decrypt(encryptPwd));}}
4、启动服务,在控制台可以看到jaspyt的默认配置(比如加密方式是PBEWithMD5AndDES):
5、在浏览器请求(端口号自定义):http://localhost:18081/jasypt ,在控制台打印信息:
加密: stqvirrvG8TcLz9mqflBDQ==
解密:123456
jasypt由于其使用的是PBEWithMD5AndDES加密方式,所以每次加密出来的结果都不一样,但是解密都是一样的,所以很适合对数据进行加密
6、将加密的结果替换配置文件中的敏感字段(这里以数据库密码为例,数据库密码是123456):
spring:application:name: service-providerdatasource: driver-class-name: com.mysql.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSourceurl: jdbc:mysql://localhost:3306/mydb?autoReconnect=true&failOverReadOnly=false&createDatabaseIfNotExist=true&useSSL=false&useUnicode=true&characterEncoding=utf8username: rootpassword: ENC(stqvirrvG8TcLz9mqflBDQ==)
上面的 ENC()是固定写法,()里面是加密后的信息。
7、在测试类中增加代码:
@Value("${spring.datasource.password}")private String dbPassword; // 数据库密码/*** 测试配置文件字段加密后,项目中该字段的值*/@GetMapping("/password")public String password() {return dbPassword;}
请求http://localhost:18081/password,会发现结果是123456,说明直接将加密文件解密出来了
扩展
a、自定义上面第6点中ENC()的固定写法。在配置文件中增加jasypt.encryptor.property:
jasypt:encryptor:#加解密秘钥password: EbfYkitulv73I2p0mXI50JMXoaxZTKJ7#设置前缀后缀property:prefix: "ENC@["suffix: "]"
b、将加解密秘钥放在配置文件中是不安全的,有如下几种解决办法:
1、在启动类上赋值秘钥:
@SpringBootApplication
public class ProviderApplication {public static void main(String[] args) {/** 配置加解密秘钥,与配置文件的密文分开放 */System.setProperty("jasypt.encryptor.password", "travel-app");
// System.setProperty("jasypt.encryptor.password", "EbfYkitulv73I2p0mXI50JMXoaxZTKJ7");SpringApplication.run(ProviderApplication.class, args);}}
2、自定义StringEncryptor:
/*** 配置StringEncryptor*/@Bean("jasyptStringEncryptor")public StringEncryptor stringEncryptor() {PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();SimpleStringPBEConfig config = new SimpleStringPBEConfig();config.setPassword("EbfYkitulv73I2p0mXI50JMXoaxZTKJ7");config.setAlgorithm("PBEWithMD5AndDES");config.setKeyObtentionIterations("1000");config.setPoolSize("1");config.setProviderName("SunJCE");config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");config.setIvGeneratorClassName("org.jasypt.salt.NoOpIVGenerator");config.setStringOutputType("base64");encryptor.setConfig(config);return encryptor;}
踩过的坑
a、必须配置加解密用的秘钥,即jasypt.encryptor.password,不然启动会报错
b、springboot2.x以下的版本,只能用jasypt1.x的版本。如果用jasypt2.x的版本,启动会报错,详见https://github.com/ulisesbocchio/jasypt-spring-boot/issues/97