数据加密概述
加密:将明文信息改变为难以读取的密文内容。
解密:将密文内容转化为原来数据。
分类
- 对称加密:加密与解密密钥相同。
- 非对称加密:加密使用公钥,公钥可公开;解密使用私钥。
相关阅读:
数据库隐私字段加密注解组件实现
说明
- 数据库存储密文字段,内存可见为明文信息
- 可设定字段保存值支持 整体加密(仅可全部匹配查询)、模糊加密(支持模糊查询)
- 相关做法: 数据库隐私字段加密以及加密后的数据如何进行模糊查询? - 业余草
MyBatis-Plus 实现
实现做法:常规二,对明文数据进行分词组合,将分词组合的结果集分别进行加密存储,查询时通过 column LIKE '%partial%'
分组规则:按固定长度,根据4位英文字符(半角),2个中文字符(全角)为一个检索条件
分组示例:ningyu1 使用4个字符为一组的加密方式 -> ning + ingy + ngyu + gyu1
-
整体加密数据库字段长度与保存值长度对应(需要额外存储一个标识符)
数据库字段长度 字符长度 varchar(49) 12个中文字符、36个ascii字符 varchar(97) 24个中文字符、72个ascii字符、3个ascii字符+23个中文字符、68个ascii字符+1个中文字符 varchar(197) 49个中文字符、145个ascii字符、3个ascii字符+48个中文字符 、 142个ascii字符+1个中文字符 varchar(253) 63个中文字符、189个ascii字符 、3个ascii字符+62个中文字符 、 186个ascii字符+1个中文字符 -
模糊加密数据库字段长度与保存值长度对应(4个字节加密一次大致对应8个字符+1个标识符),根据4位英文字符(半角),2个中文字符(全角)为一个检索条件
数据库字段长度 字符长度 varchar(99) 12个中文字符、14个ascii字符 varchar(198) 23个中文字符、25个ascii字符 varchar(252) 29个中文字符、31个ascii字符
1 :利用 TypeHandler 支持数据加解密转换
INSERT VALUE、UPDATE ENTITY、SELECT RESULT
只对数据库和程序之间的数据转换,查询条件不会调用。
-
整体加密类型处理器
使用示例: 1. MyBatis-Plus 注解(自动生产 ResultMap ,存在场景不生效) @TableField(typeHandler = OverallCryptoTypeHandler.class) 2. 自定义 ResultMap 配置 <result column="phone" property="phone" typeHandler="cn.eastx.practice.demo.crypto.config.mp.OverallCryptoTypeHandler" />
整体加密类型处理器 OverallCryptoTypeHandler.java
@Override public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { /* 对非null参数值进行加密,需要通过实体类处理方可,支持 INSERT/UPDATE ENTITY 当前处理 INSERT ENTITY,UPDATE ENTITY 会先通过拦截器处理 因为拦截器修改元数据将导致实体类属性值产生变更,所以实体类还是由 TypeHandler 来进行处理 */ ps.setString(i, CryptoDataUtil.overallEncrypt(parameter)); } @Override public String getNullableResult(ResultSet rs, String columnName) throws SQLException { // 对可为null的结果进行解密 return CryptoDataUtil.decrypt(rs.getString(columnName)); }
-
模糊加密类型处理器
注意:根据4位英文字符(半角),2个中文字符(全角)为一个检索条件,如果字段值较少查询可能存在问题使用示例: 1. MyBatis-Plus 注解(自动生产 ResultMap ,存在场景不生效) @TableField(typeHandler = FuzzyCryptoTypeHandler.class) 2. 自定义 ResultMap 配置 <result column="phone" property="phone" typeHandler="cn.eastx.practice.demo.crypto.config.mp.FuzzyCryptoTypeHandler" />
模糊加密类型处理器 FuzzyCryptoTypeHandler.java
@Override public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { /* 对非null参数值进行加密,需要通过实体类处理方可,支持 INSERT/UPDATE ENTITY 当前处理 INSERT ENTITY,UPDATE ENTITY 会先通过拦截器处理 因为拦截器修改元数据将导致实体类属性值产生变更,所以实体类还是由 TypeHandler 来进行处理 */ ps.setString(i, CryptoDataUtil.fuzzyEncrypt(parameter)); } @Override public String getNullableResult(ResultSet rs, String columnName) throws SQLException { // 对可为null的结果进行解密 return CryptoDataUtil.decrypt(rs.getString(columnName)); }
2 :利用字段注解配合 MyBatis 拦截器对条件进行拦截处理
注:目前仅支持简单查询处理,复杂查询可能存在问题。
-
自定义字段注解
CryptoCond.java
- 使用
replacedColumn()
替换 SQL 查询条件中的字段名 - 使用
encryption()
对 SQL 中条件值、参数值进行加密,支持两种方式(整体匹配、模糊匹配) - 使用示例:
User.java
- 使用
-
自定义 MyBatis 拦截器
- 实现 Interceptor 接口,重写拦截器拦截 SQL 逻辑
- 拦截器执行在 TypeHandler 之前,注意避免冲突
自定义 MyBatis 拦截器 CryptoCondInterceptor.java
@Override public Object intercept(Invocation inv