本篇文章为你整理了数据加密(数据加密方式有哪些)的详细内容,包含有数据加密技术 数据加密方式有哪些 数据加密传输 数据加密存储 数据加密,希望能帮助你了解 数据加密。
数据库存储密文字段,内存可见为明文信息
可设定字段保存值支持 整体加密(仅可全部匹配查询)、模糊加密(支持模糊查询)
相关做法: 数据库隐私字段加密以及加密后的数据如何进行模糊查询? - 业余草
实现做法:常规二,对明文数据进行分词组合,将分词组合的结果集分别进行加密存储,查询时通过 column LIKE %partial%
分组规则:按固定长度,根据4位英文字符(半角),2个中文字符(全角)为一个检索条件
分组示例:ningyu1 使用4个字符为一组的加密方式 - ning + ingy + ngyu + gyu1
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个中文字符(全角)为一个检索条件
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));
使用 replacedColumn() 替换 SQL 查询条件中的字段名
使用 encryption() 对 SQL 中条件值、参数值进行加密,支持两种方式(整体匹配、模糊匹配)
使用示例:User.java
实现 Interceptor 接口,重写拦截器拦截 SQL 逻辑
拦截器执行在 TypeHandler 之前,注意避免冲突
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler statementHandler = PluginUtils.realTarget(invocation.getTarget());
MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
MappedStatement mappedStatement =
(MappedStatement) metaObject.getValue("delegate.mappedStatement");
// 支持处理 SELECT、UPDATE、DELETE
boolean canHandler = Stream.of(SqlCommandType.SELECT, SqlCommandType.UPDATE,
SqlCommandType.DELETE)
.anyMatch(item - item.equals(mappedStatement.getSqlCommandType()));
if (canHandler !getIntercept()) {
clearIntercept();
return invocation.proceed();
clearIntercept();
// 判断是否有参数需要处理
BoundSql boundSql = statementHandler.getBoundSql();
if (Objects.isNull(boundSql.getParameterObject())) {
return invocation.proceed();
// 获取自定义注解,通过 MapperID 获取到 Mapper 对应的实体类,获取实体类所有注解字段与注解对应 Map
Map String, CryptoCond condMap = mapEntityFieldCond(mappedStatement.getId());
if (CollectionUtil.isNotEmpty(condMap)) {
replaceHandle(mappedStatement.getConfiguration(), condMap, boundSql);
return invocation.proceed();
// 替换数据处理
private void replaceHandle(Configuration configuration, Map String, CryptoCond condMap,
BoundSql boundSql) {
String sql = boundSql.getSql();
Pair String, List SqlCondOperation sqlPair = SqlUtil.getSqlCondOperationPair(sql);
List SqlCondOperation operationList = sqlPair.getValue();
if (CollectionUtil.isEmpty(operationList)) {
return;
sql = sqlPair.getKey();
MetaObject paramMetaObject = configuration.newMetaObject(boundSql.getParameterObject());
List ParameterMapping mappings = boundSql.getParameterMappings();
int mappingStartIdx = 0;
int addIdxLen = 0;
for (SqlCondOperation operation : operationList) {
String condStr = operation.getOriginCond();
int prepareNum = SqlUtil.countPreparePlaceholder(condStr);
CryptoCond ann = condMap.get(operation.getColumnName());
if (Objects.nonNull(ann)) {
// 替换查询条件参数中的列名
if (StrUtil.isNotBlank(ann.replacedColumn()) !operation.checkSetCond()) {
sql = operation.replaceSqlCond(sql, addIdxLen,
operation.getColumnName(), ann.replacedColumn());
// 替换属性值为加密值
if (prepareNum == 0) {
// 存在非预编译语句条件,直接替换 SQL 条件值
String propVal =
String.valueOf(paramMetaObject.getValue(operation.getColumnName()));
String useVal = getCryptoUseVal(ann, propVal);
sql = operation.replaceSqlCond(sql, addIdxLen, propVal, useVal);
} else {
// 预编译语句条件通过替换条件值处理
for (int i = 0; i prepareNum; i++) {
String propName = mappings.get(mappingStartIdx + i).getProperty();
if (!propName.startsWith("et.")) {
// 非实体类属性进行值替换,实体类属性通过 TypeHandler 处理
String propVal = String.valueOf(paramMetaObject.getValue(propName));
paramMetaObject.setValue(propName, getCryptoUseVal(ann, propVal));
mappingStartIdx += prepareNum;
addIdxLen += operation.getOriginCond().length() - condStr.length();
ReflectUtil.setFieldValue(boundSql, "sql", sql);
执行 /resources/db/schema.sql 创建数据库( java-practice-demos )、示例表( crypto-user )
用户表 Service 层 IUserService.java
用户表 Service 层 测试 UserServiceTest.java
使用问题
点击查看代码 UserMapper.xml
!-- 使用自定义SQL时,对于加密处理需要使用ResultMap作为返回对象,否则对解析成实际数据会存在问题 --
resultMap id="BaseResultMap" type="cn.eastx.practice.demo.crypto.pojo.po.User"
result column="id" property="id" /
result column="name" property="name" /
result column="password" property="password" /
result column="salt" property="salt" /
result column="phone" property="phone" typeHandler="cn.eastx.practice.demo.crypto.config.mp.OverallCryptoTypeHandler" /
result column="email" property="email" typeHandler="cn.eastx.practice.demo.crypto.config.mp.FuzzyCryptoTypeHandler" /
result column="create_time" property="createTime" /
result column="update_time" property="updateTime" /
/resultMap
设置 CryptoCondInterceptor.setIntercept(false)
在实体类上相应字段设置 @CryptoCond ,示例:User.java
@TableField(typeHandler = OverallCryptoTypeHandler.class)
@CryptoCond(encryption = CryptoCond.EncryptionEnum.DEFAULT_OVERALL)
private String phone;
* 邮箱,模糊加密
@TableField(typeHandler = FuzzyCryptoTypeHandler.class)
@CryptoCond(encryption = CryptoCond.EncryptionEnum.DEFAULT_FUZZY)
private String email;
* 创建时间
@TableField(fill = INSERT)
private LocalDateTime createTime;
* 更新时间
@TableField(fill = INSERT_UPDATE)
private LocalDateTime updateTime;
Mapper 实现 BaseMapper 并指定实体类,示例:public interface UserMapper extends BaseMapper User
将拦截器加入 Spring IOC 管理
以上就是数据加密(数据加密方式有哪些)的详细内容,想要了解更多 数据加密的内容,请持续关注盛行IT软件开发工作室。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。