配置文件、API接口脱敏
一、配置文件脱敏
1、概述
核心隐私数据无论对于企业还是用户来说尤其重要,因此要想办法杜绝各种隐私数据的泄漏。对于工程中的敏感信息,与数据库打交道的的工程肯定是配置数据源,尤其是数据库的账号密码
,我们不想把它们明文
写在配置文件里,又想让工程能正确跑起来,那应该怎么做呢?
**由于数据库的敏感性,所以不可能让每个人都知道su ****root
的密码。且数据库中权限、视图这些机制也是为了保证安全性,所以要保证让尽可能少的人知道root
**的密码。所以我们可以利用非对称加密算法的思想:
- 在工程的配置文件中写入加密好的
密文
。 - 启动工程时让知道
密钥
的人,以启动参数的形式将密钥
输入进去。 - 工程根据
密钥
,将密文
自动解密为明文
,用来完成配置。 - 无关的人是无法知道敏感信息的
明文
是什么的
这里我们使用一款开源插件:
jasypt-spring-boot
来进行脱敏处理,项目地址:https://github.com/ulisesbocchio/jasypt-spring-boot
2、利用jar包手动加密
1 | # 使用秘钥和密码明文生成密码 |
3、SpringBoot实现脱敏
3.1 代码实现
首先引入依赖
1 | <dependency> |
然后进行密钥的配置(配置文件),当然将秘钥直接放在配置文件中也是不安全的,我们可以在项目启动的时候配置秘钥java -jar xxx.jar -Djasypt.encryptor.password=dGNtLW1hbmFnZS1zeXN0ZW
1 | jasypt: |
然后可以对明文进行加密
1 |
|
然后将加密后的密文写入配置,jasypt
默认使用ENC()
包裹,此时的数据源配置如下
1 | spring: |
上述配置是使用默认的prefix=ENC(
、suffix=)
,当然我们可以根据自己的要求更改,只需要在配置文件中更改即可,如下:
1 | jasypt: |
那么此时的配置就必须使用PASS()
包裹才会被解密,如下:
1 | spring: |
3.2 运行原理
- **jasypt的加密方式 **
jasypt采用PBEWithMD5AndDES
加密方式,在相同的秘钥情况下,每次生成的密文都不相同,但可以使用秘钥解密获得相同的明文,可以确保秘钥的安全性 - **jasypt-spring-boot-starter的运行原理 **
先使用原先的配置加载方式加载配置信息(因此系统使用何种配置方式,对加解密没有影响),再通过代理的方式代理了配置获取类,在Bean生成时加载配置的地方使用代理类执行密码转换获得明文 - **jasypt-spring-boot-starter工作原理 **
在spring中的加载方式:EnableEncryptablePropertiesConfiguration 类
负责配置文件加载将当前的environment环境配置进行代理或包装(返回EnableEncryptablePropertiesBeanFactoryPostProcessor
)对所有的参数值使用Encryptable进行代理,生成PropertySource
的AOP代理类 并使用EncryptableMapPropertySourceWrapper
类来包装PropertySource 使用的时候通过DefaultPropertyDetector
来判断数据是否符合ENC(**********)
这样的数据结构 符合时,使用EncryptablePropertyResolver
来解码数据
4、其他注意事项说明
对于密文使用,可以支持nacos配置中心,yml等多种配置文件;项目启动参数增加【-Djasypt.encryptor.password=秘钥】 来实现密文解密 ;最后关于加密结果,每次加密的结果都不一样,但使用秘钥都能得到正确的明文,注意加解密一定需要使用jasypt-spring-boot-starter
中引用的jasypt-x.x.x.jar
对应版本,否则可能导致密文无法解析的情况
二、接口返回数据脱敏
1、概述
通常接口返回值中的一些敏感数据也是要脱敏的,因为不脱敏的敏感数据,可能会引起用户的不满。比如身份证号、手机号码、地址等通常的手段就是用*
隐藏一部分数据,当然也可以根据自己需求定制。言归正传,如何优雅的实现呢?有两种实现方案:
- 整合Mybatis插件,在查询的时候针对特定的字段进行脱敏
- 整合Jackson,在序列化阶段对特定字段进行脱敏
这里我们就先使用第二种方法对数据进行脱敏
2、SpringBoot实战
首先定制脱敏策略,针对项目需求,定制不同字段的脱敏规则,比如手机号中间几位用*
替代,不同项目可以根据自己需求进行删减
1 | /** |
第二步自定义一个脱敏注解,一旦有属性被标注,则进行对应得脱敏
1 | /** |
下面将是重要实现,对标注注解@Sensitive
的字段进行脱敏,实现如下,其中createContextual
的作用是通过字段已知的上下文信息定制JsonSerializer
对象
1 | /** |
然后定义Person类,对其数据脱敏,使用注解@Sensitive
注解进行数据脱敏
1 |
|
最后模拟接口测试
1 |
|
输出结果
1 | { |
参考文章
https://blog.csdn.net/zym_1321/article/details/122198121