加密配置文件里面的敏感数据
项目开发的时候,需要把数据存放到指定的数据库中(例如MySql、Oracle等),还有会使用缓存数据库提升性能的。连接数据库相关的信息一般都是存放在配置文件里面,spring boot会帮我们注入到具体的对象里面。但是如果配置文件里面相关的敏感信息是以【明文】的方式存储,那么就会存在安全隐患
今天偶然想起是不是可以把敏感信息加密起来,然后写到配置文件里面,结果一搜,还真的有,特此记录一下!
通用步骤(引入相关依赖)
com.github.ulisesbocchio
jasypt-spring-boot-starter
3.0.3
数据库信息
redis缓存信息
修改配置文件,加入密钥
修改前的yml配置文件
server:
port: 9091
jasypt:
encryptor:
# 指定加密密码
password: wxzkjtvvgt@44lvvz
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/encryp?serverTimezone=UTC
driver-class-name: com.mysql.cj.jdbc.Driver
password: root1234
username: root
application:
name: test-encrypt
redis:
port: 6379
host: 127.0.0.1
password: iamamg
第一种做法
@Test
void testEncrypt() {
final String redisHostEncrypt = stringEncryptor.encrypt("127.0.0.1");
final String redisPasswordEncrypt = stringEncryptor.encrypt("iamamg");
final String mysqlUrl = stringEncryptor.encrypt("jdbc:mysql://127.0.0.1:3306/encryp?serverTimezone=UTC");
final String mysqlUserName = stringEncryptor.encrypt("root");
final String mysqlPassword = stringEncryptor.encrypt("root1234");
System.out.println("==================================");
// 用这些加密的信息替换掉配置文件里面相关的配置项
System.out.println("redis主机加密:" + redisHostEncrypt);
System.out.println("redis密码加密:" + redisPasswordEncrypt);
System.out.println("mysql用户名加密:" + mysqlUserName);
System.out.println("mysql密码加密:" + mysqlPassword);
System.out.println("mysqlUrl加密:" + mysqlUrl);
System.out.println("===================================");
System.out.println("redis主机解密:" + stringEncryptor.decrypt(redisHostEncrypt));
System.out.println("redis密码解密:" + stringEncryptor.decrypt(redisPasswordEncrypt));
System.out.println("mysql用户名解密:" + stringEncryptor.decrypt(mysqlUserName));
System.out.println("mysql密码解密:" + stringEncryptor.decrypt(mysqlPassword));
System.out.println("mysqlUrl解密:" + stringEncryptor.decrypt(mysqlUrl));
}
==================================
redis主机加密:V5FeblAg4MRY+TEkmBlSZzgK74CTIyPPnrkcpUibYFMxbEHtmPWduLxdHpgFn3Gw
redis密码加密:0aP2oNj2IrXA9bl6HygZQESEy82dWccigQ5Fic474y8f3pyDNxRIdA+C5SjHsKEY
mysql用户名加密:cTPlLHJqZcchsnd0N9gZWGpFcfAFS0EwFwT0foYPXqxA9ngXfNtCUoR7rLvPfYRF
mysql密码加密:/J2IBQyk8aydeBKL6E553ffxanVE660uuNOzUrNlVMEcrejy70Sen0MKkXc7szQ0
mysqlUrl加密:NvHXbj9LhVamadZSyXfB/Alsg+XuICiJUKTC/dl92lDEF0gcHoIi1Fd0HOxGOEBydgnyNdyK0cnDC0vyC0k+e5AR9Cr8VYDUMdALMr+85Ar4XrPZ0ZICYAsox84fSMdb
===================================
redis主机解密:127.0.0.1
redis密码解密:iamamg
mysql用户名解密:root
mysql密码解密:root1234
mysqlUrl解密:jdbc:mysql://127.0.0.1:3306/encryp?serverTimezone=UTC
修改后的yml配置文件
可能你也观察到了,需要额外注意的一点就是,需要加密的数据项都使用了ENC()括起来了
server:
port: 9091
jasypt:
encryptor:
# 加密密码
password: wxzkjtvvgt@44lvvz
spring:
datasource:
url: ENC(NvHXbj9LhVamadZSyXfB/Alsg+XuICiJUKTC/dl92lDEF0gcHoIi1Fd0HOxGOEBydgnyNdyK0cnDC0vyC0k+e5AR9Cr8VYDUMdALMr+85Ar4XrPZ0ZICYAsox84fSMdb)
driver-class-name: com.mysql.cj.jdbc.Driver
password: ENC(/J2IBQyk8aydeBKL6E553ffxanVE660uuNOzUrNlVMEcrejy70Sen0MKkXc7szQ0)
username: ENC(cTPlLHJqZcchsnd0N9gZWGpFcfAFS0EwFwT0foYPXqxA9ngXfNtCUoR7rLvPfYRF)
application:
name: test-encrypt
redis:
port: 6379
host: ENC(V5FeblAg4MRY+TEkmBlSZzgK74CTIyPPnrkcpUibYFMxbEHtmPWduLxdHpgFn3Gw)
password: ENC(0aP2oNj2IrXA9bl6HygZQESEy82dWccigQ5Fic474y8f3pyDNxRIdA+C5SjHsKEY)
测试是否可行
/**
* 测试获取数据库中的数据总量
*/
@Test
void testSelectInMysql() {
String sql = "SELECT COUNT(1) FROM T0001_TEST";
final Integer num = jdbcTemplate.queryForObject(sql, Integer.class);
System.out.println(num);
}
/**
* 测试获取redis中指定key
*/
@Test
void testSelectInRedis() {
final String name = redisTemplate.opsForValue().get("name");
System.out.println(name);
}
但是,大家且思考一下,我们当前yml配置文件里面依然存在着密钥,这是不是很不合理?只要解读到这个文件,密钥还是会被知道,所以这里提供另外一种做法
第二种做法
- 首先把yml文件里面的密钥记录下来,然后把配置去掉(其实就是把这个配置移到运行的时候才指定) 启动的时候加上-Djasypt.encryptor.password= 密钥 ;这里的密钥为 wxzkjtvvgt@44lvvz,如果密钥错误,项目是启动不成功的,通常报的错都是数据库连接失败,这也挺正常的,因为如果是错误的密钥,密文信息就无法解密,得到的自然是不符合的信息,所以会报错
就把关于密钥的部分移除,其他依旧不变
server:
port: 9091
spring:
datasource:
url: ENC(NvHXbj9LhVamadZSyXfB/Alsg+XuICiJUKTC/dl92lDEF0gcHoIi1Fd0HOxGOEBydgnyNdyK0cnDC0vyC0k+e5AR9Cr8VYDUMdALMr+85Ar4XrPZ0ZICYAsox84fSMdb)
driver-class-name: com.mysql.cj.jdbc.Driver
password: ENC(/J2IBQyk8aydeBKL6E553ffxanVE660uuNOzUrNlVMEcrejy70Sen0MKkXc7szQ0)
username: ENC(cTPlLHJqZcchsnd0N9gZWGpFcfAFS0EwFwT0foYPXqxA9ngXfNtCUoR7rLvPfYRF)
application:
name: test-encrypt
redis:
port: 6379
host: ENC(V5FeblAg4MRY+TEkmBlSZzgK74CTIyPPnrkcpUibYFMxbEHtmPWduLxdHpgFn3Gw)
password: ENC(0aP2oNj2IrXA9bl6HygZQESEy82dWccigQ5Fic474y8f3pyDNxRIdA+C5SjHsKEY)
- 在IDEA里面启动程序的方式
- 打成jar包,命令行启动的方式
最终还是测试是否可行
此时模拟真实的三层开发
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XI4lgeHt-1618718221907)(D:\typora\images\三层开发.png)]
//controller代码
/**
* @Author: Amg
* @Date: Created in 17:45 2021/04/17
* @Description: TODO
*/
@RestController
public class TestController {
@Autowired
TestServiceImpl service;
@GetMapping("/count")
public String getCount() {
final Integer count = service.getCount();
if (StringUtils.isEmpty(count)) {
return "连接数据库出问题了";
} else {
return "连接数据库成功!当前数据量为:" + count;
}
}
}
//service代码
/**
* @Author: Amg
* @Date: Created in 17:46 2021/04/17
* @Description: TODO
*/
@Service
public class TestServiceImpl {
@Autowired
private JdbcTemplate jdbcTemplate;
public Integer getCount() {
try {
String sql = "SELECT COUNT(1) FROM T0001_TEST";
return jdbcTemplate.queryForObject(sql, Integer.class);
} catch (DataAccessException e) {
e.printStackTrace();
return null;
}
}
}
莫得问题!
总结
1、引入相关依赖
2、修改配置文件,加入密钥配置 / 启动的时候指定密钥
Original: https://www.cnblogs.com/iamamg97/p/14673147.html
Author: 码农Amg
Title: 加密配置文件里面的敏感数据
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/570341/
转载文章受原作者版权保护。转载请注明原作者出处!