如何加密配置文件里的敏感数据

 更新时间:2022年06月17日 09:28:42   作者:码农Amg  
这篇文章主要介绍了加密配置文件里的敏感数据的实现方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

加密配置文件里面的敏感数据

项目开发的时候,需要把数据存放到指定的数据库中(例如MySql、Oracle等),还有会使用缓存数据库提升性能的。

连接数据库相关的信息一般都是存放在配置文件里面,spring boot会帮我们注入到具体的对象里面。但是如果配置文件里面相关的敏感信息是以【明文】的方式存储,那么就会存在安全隐患

今天偶然想起是不是可以把敏感信息加密起来,然后写到配置文件里面,结果一搜,还真的有,特此记录一下!

通用步骤(引入相关依赖)

<dependency>
    <groupId>com.github.ulisesbocchio</groupId>
    <artifactId>jasypt-spring-boot-starter</artifactId>
    <version>3.0.3</version>
</dependency>

数据库信息

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配置文件里面依然存在着密钥,这是不是很不合理?只要解读到这个文件,密钥还是会被知道,所以这里提供另外一种做法

第二种做法

1.首先把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)

2.在IDEA里面启动程序的方式

3.打成jar包,命令行启动的方式

最终还是测试是否可行

此时模拟真实的三层开发

//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、修改配置文件,加入密钥配置 / 启动的时候指定密钥

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 浅谈Java8新特性Predicate接口

    浅谈Java8新特性Predicate接口

    这篇文章主要介绍了浅谈Java8新特性Predicate接口,文中有非常详细的代码示例,对正在学习java的小伙伴们有很好的帮助,需要的朋友可以参考下
    2021-05-05
  • Java实现二维码生成的代码方法

    Java实现二维码生成的代码方法

    这篇内容分享了JAVA实现二维码生成的实例代码,对此有需要的朋友们可以测试参考下。
    2018-07-07
  • java中lombok的@Data引发问题详解

    java中lombok的@Data引发问题详解

    这篇文章主要给大家介绍了关于java中lombok的@Data引发问题的相关资料,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • mybatis配置mapper-locations位置的三种方式小结

    mybatis配置mapper-locations位置的三种方式小结

    这篇文章主要给大家介绍了关于mybatis配置mapper-locations位置的三种方式,Mybatis-Plus的初衷是为了简化开发,而不建议开发者自己写SQL语句的,但是有时客户需求比较复杂,需要的朋友可以参考下
    2023-08-08
  • 浅析SpringBoot自动装配的实现

    浅析SpringBoot自动装配的实现

    springboot开箱即用,其实实现了自动装配,本文重点给大家介绍SpringBoot是如何做到自动装配的,感兴趣的朋友跟随小编一起看看吧
    2022-02-02
  • springboot启动前执行方法的四种方式总结

    springboot启动前执行方法的四种方式总结

    这篇文章主要给大家介绍了关于springboot启动前执行方法的四种方式,文中通过实例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2022-01-01
  • java使用swing绘制国际象棋棋盘

    java使用swing绘制国际象棋棋盘

    这篇文章主要为大家详细介绍了java使用swing绘制国际象棋棋盘,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-05-05
  • 教你java面试时如何聊单例模式

    教你java面试时如何聊单例模式

    这篇文章主要给大家介绍了关于Java单例模式推荐的几种模式,文中通过示例代码介绍的非常详细,对大家学习或者使用Java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2021-06-06
  • 如何基于java实现Gauss消元法过程解析

    如何基于java实现Gauss消元法过程解析

    这篇文章主要介绍了如何基于java实现Gauss消元法过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • Java实现高效PDF文件传输技巧

    Java实现高效PDF文件传输技巧

    你是否曾为PDF文件传输的低效率而苦恼?现在,有了这份Java实现高效PDF文件传输技巧指南,你将能够轻松解决这个问题,我们将分享一些实用的技巧和最佳实践,帮助你优化文件传输过程,不要错过这个提高工作效率的机会,快来阅读这份指南吧!
    2024-03-03

最新评论