导语
背景
由滴滴事件引发国家对数据安全的一系列反应,为贯彻国家的政策、维护数据的安全,我们公司也开始着手对系统中存储的敏感数据进行加密。
目前我们组管理的系统包含敏感数据字段包括:姓名、证件号、电话、邮箱、住址等。
国家层面
- 数据安全保障能力是国家竞争力的直接体现;
- 数据保护与安全是国家安全的重要方面;
- 数据安全有序是数字经济健康发展的基础;
- 数据安全是国家数字治理的重要议题。
企业层面
- 数据安全保障直接影响企业与客户的关系;
- 数据安全在企业信息化建设中占据主导地位。
项目中的加解密流程
概述
1、搭建新库,与需要做加密的旧库建立主从关系;
2、同步数据;
3、数据由旧库向新库同步完成(接近 100%);
4、启动定时任务,从旧库取数据,在程序中进行加密,按照 id
更新到新库;(保证幂等)
5、更新完成后,通过修改数据源配置切换到加密后的数据源;
6、部署上线包含加解密逻辑的业务代码。
流程图
补偿处理
由于数据量较大,采用分页进行加密,并用 redis 记录加密的最新页码,执行到某一页加密失败时,查明失败原因,修复程序,重新执行定时加密,此时加密的页码从出错页码开始执行,避免重头开始进行全量数据加密导致耗时。(如果要重头开始跑,可以通过输入指定参数清除 Redis 缓存重新跑全量加密)
对定时任务加密完成后,切换数据源上线加解密业务代码的期间的增量数据(未加密数据),仍旧可以通过启动定时任务加密。
多数据源配置
流程
1、自定义类 DynamicDataSource 继承 AbstractRoutingDatasource 类并注入 bean;
2、将所有数据源写入到 AbstractRoutingDatasource 类中;
3、以注解+切面的形式实现数据源的切换;
具体做法:
1)、在需要切换数据源的方法上标注注解,声明要切换后的数据源;
2)、执行到标注注解的方法时,通过切面获取到方法注解的 数据源名称;
3)、将数据源名称 set 进入当前线程中。
4、执行注解方法里的 mapper 时,AbstractRoutingDatasource.getConnection()方法调用
determineTargetDataSource(),该方法又调用 determineCurrentLookupKey()方法,获取
到第三步当前线程保存的数据源名称;
5、根据数据源 map 集合和作为 key 的数据源名称,获取到切换的数据源。
初始化数据源并注入到 bean 中
多数据源切换
使用注解+切面的方式实现数据源的动态切换
1 |
|
AbstractRoutingDatasource 核心代码
数据加解密的方式
SQL 函数实现加解密
采用 Mysql 内置的 AES 加解密函数,对某个字段进行加解密,如下。
1 | -- 加密 张三 |
使用场景:
需求小,指定加密内容,该方法可行。
密钥变 ,所有代码跟着变。
不推荐。
TypeHandler 实现
- Mybatis 的类型转换器,可将 java 数据类型转换成与数据库适配的格式。
- 加解密中的使用
自定义 EncryptionHandler 继承 BaseTypeHandler,重写里面的 setNonNullParameter 和 getNonableResult 方法,在敏感数据入库前做加密处理,在敏感数据出库时做解密处理。
- 加密
- 解密