mybatis-plus拦截器敏感字段加解密的实现方法是什么
发表于:2026-11-02 作者:千家信息网编辑
千家信息网最后更新 2026年11月02日,本篇内容主要讲解"mybatis-plus拦截器敏感字段加解密的实现方法是什么",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"mybatis-plus拦截器
千家信息网最后更新 2026年11月02日mybatis-plus拦截器敏感字段加解密的实现方法是什么
本篇内容主要讲解"mybatis-plus拦截器敏感字段加解密的实现方法是什么",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"mybatis-plus拦截器敏感字段加解密的实现方法是什么"吧!
背景
数据库在保存数据时,对于某些敏感数据需要脱敏或者加密处理,如果一个一个的去加显然工作量大而且容易出错,这个时候可以考虑使用拦截器,本文针对的是mybatis-plus作为持久层框架,其他场景未测试。代码如下:
一、查询拦截器
package com.sfpay.merchant.service.interceptor; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;import com.sfpay.merchant.service.service.CryptService;import lombok.extern.slf4j.Slf4j;import org.apache.ibatis.binding.MapperMethod;import org.apache.ibatis.cache.CacheKey;import org.apache.ibatis.executor.Executor;import org.apache.ibatis.mapping.BoundSql;import org.apache.ibatis.mapping.MappedStatement;import org.apache.ibatis.plugin.Interceptor;import org.apache.ibatis.plugin.Intercepts;import org.apache.ibatis.plugin.Invocation;import org.apache.ibatis.plugin.Signature;import org.apache.ibatis.session.ResultHandler;import org.apache.ibatis.session.RowBounds;import org.springframework.beans.factory.annotation.Autowired; import java.util.ArrayList;import java.util.Map;import java.util.Objects; /** * @describe: 查询拦截器 * 查询条件加密使用方式:使用 @Param("decrypt")注解的自定义类型 * 返回结果解密使用方式: ①在自定义的DO上加上注解 CryptAnnotation ②在需要加解密的字段属性上加上CryptAnnotation * @author: *** * @date: 2021/3/30 17:51 */@Slf4j@Intercepts({ @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}), @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})public class QueryInterceptor implements Interceptor { /** * 查询参数名称,ParamMap的key值 */ private static final String DECRYPT = "decrypt"; @Autowired private CryptService cryptService; @Autowired private UpdateInterceptor updateInterceptor; @Override public Object intercept(Invocation invocation) throws Throwable { //获取查询参数,查询条件是否需要加密 Object[] args = invocation.getArgs(); Object parameter = args[1]; Object result = null; //设置执行标识 boolean flag = true; if (parameter instanceof MapperMethod.ParamMap) { Map paramMap = (Map) parameter; if (paramMap.containsKey(DECRYPT)) { Object queryParameter = paramMap.get(DECRYPT); if (updateInterceptor.needToCrypt(queryParameter)) { //执行sql,还原加密后的报文 MappedStatement mappedStatement = (MappedStatement) args[0]; result = updateInterceptor.proceed(invocation, mappedStatement, queryParameter); flag = false; } } } //是否需要执行 if (flag) { result = invocation.proceed(); } if (Objects.isNull(result)) { return null; } // 返回列表数据,循环检查 if (result instanceof ArrayList) { ArrayList resultList = (ArrayList) result; if (CollectionUtils.isNotEmpty(resultList) && updateInterceptor.needToCrypt(resultList.get(0))) { for (Object o : resultList) { cryptService.decrypt(o); } } } else if (updateInterceptor.needToCrypt(result)) { cryptService.decrypt(result); } //返回结果 return result; }}二、插入和更新拦截器
package com.sfpay.merchant.service.interceptor; import com.baomidou.mybatisplus.annotation.TableId;import com.sfpay.merchant.common.util.annotation.CryptAnnotation;import com.sfpay.merchant.service.service.CryptService;import org.apache.ibatis.binding.MapperMethod;import org.apache.ibatis.executor.Executor;import org.apache.ibatis.mapping.MappedStatement;import org.apache.ibatis.mapping.SqlCommandType;import org.apache.ibatis.plugin.Interceptor;import org.apache.ibatis.plugin.Intercepts;import org.apache.ibatis.plugin.Invocation;import org.apache.ibatis.plugin.Signature;import org.apache.ibatis.session.defaults.DefaultSqlSession;import org.springframework.beans.BeanUtils;import org.springframework.beans.factory.annotation.Autowired; import java.lang.reflect.Field;import java.lang.reflect.InvocationTargetException;import java.util.Arrays;import java.util.Map;import java.util.Objects;import java.util.Optional; /** * @describe: 数据库更新操作拦截器 * 一、支持的使用场景 * ①场景一:通过mybatis-plus BaseMapper自动映射的方法 * ②场景一:通过mapper接口自定义的方法,更新对象为自定义DO * 二、使用方法 * ①在自定义的DO上加上注解 CryptAnnotation * ②在需要加解密的字段属性上加上CryptAnnotation * ③自定义映射方法在需要加解密的自定义DO参数使用@Param("et") * @author: *** * @date: 2021/3/31 17:51 */@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})public class UpdateInterceptor implements Interceptor { @Autowired private CryptService cryptService; /** * 更新参数名称,ParamMap的key值 */ private static final String CRYPT = "et"; @Override public Object intercept(Invocation invocation) throws Throwable { //代理类方法参数,该拦截器拦截的update方法有两个参数args = {MappedStatement.class, Object.class} Object[] args = invocation.getArgs(); //获取方法参数 MappedStatement mappedStatement = (MappedStatement) args[0]; Object parameter = args[1]; if (Objects.isNull(parameter)) { //无参数,直接放行 return invocation.proceed(); } // 如果是多个参数或使用Param注解(Param注解会将参数放置在ParamMap中) if (parameter instanceof MapperMethod.ParamMap) { Map paramMap = (Map) parameter; if (paramMap.containsKey(CRYPT)) { Object updateParameter = paramMap.get(CRYPT); if (needToCrypt(updateParameter)) { //执行sql,还原加解密后的报文 return proceed(invocation, mappedStatement, updateParameter); } } } else if (parameter instanceof DefaultSqlSession.StrictMap) { //不知道是啥意思,直接过 return invocation.proceed(); } else if (needToCrypt(parameter)) { //执行sql,还原加解密后的报文 return proceed(invocation, mappedStatement, parameter); } //其他场景直接放行 return invocation.proceed(); } /** * 执行sql,还原加解密后的报文 * * @param invocation * @param mappedStatement * @param parameter * @return * @throws IllegalAccessException * @throws InstantiationException * @throws InvocationTargetException */ Object proceed(Invocation invocation, MappedStatement mappedStatement, Object parameter) throws IllegalAccessException, InstantiationException, InvocationTargetException { //先复制一个对象备份数据 Object newInstance = newInstance(parameter); //调用加解密服务 cryptService.encrypt(parameter); //执行操作,得到返回结果 Object result = invocation.proceed(); //把加解密后的字段还原 reductionParameter(mappedStatement, newInstance, parameter); //返回结果 return result; } /** * 先复制一个对象备份数据,便于加解密后还原原报文 * * @param parameter * @return * @throws IllegalAccessException * @throws InstantiationException */ private Object newInstance(Object parameter) throws IllegalAccessException, InstantiationException { Object newInstance = parameter.getClass().newInstance(); BeanUtils.copyProperties(parameter, newInstance); return newInstance; } /** * 把加解密后的字段还原,同时把mybatis返回的tableId返回给参数对象 * * @param mappedStatement * @param newInstance * @param parameter * @throws IllegalAccessException */ private void reductionParameter(MappedStatement mappedStatement, Object newInstance, Object parameter) throws IllegalAccessException { //获取映射语句命令类型 SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType(); if (SqlCommandType.INSERT == sqlCommandType) { //从参数属性中找到注解是TableId的字段 Field[] parameterFields = parameter.getClass().getDeclaredFields(); Optional optional = Arrays.stream(parameterFields).filter(field -> field.isAnnotationPresent(TableId.class)).findAny(); if (optional.isPresent()) { Field field = optional.get(); field.setAccessible(true); Object id = field.get(parameter); //覆盖参数加解密的值 BeanUtils.copyProperties(newInstance, parameter); field.set(parameter, id); } else { //覆盖参数加解密的值 BeanUtils.copyProperties(newInstance, parameter); } } else { //覆盖参数加解密的值 BeanUtils.copyProperties(newInstance, parameter); } } /** * 是否需要加解密: * ①是否属于基本类型,void类型和String类型,如果是,不加解密 * ②DO上是否有注解 ③ 属性是否有注解 * * @param object * @return */ public boolean needToCrypt(Object object) { if (object == null) { return false; } Class> clazz = object.getClass(); if (clazz.isPrimitive() || object instanceof String) { //基本类型和字符串不加解密 return false; } //获取DO注解 boolean annotationPresent = clazz.isAnnotationPresent(CryptAnnotation.class); if (!annotationPresent) { //无DO注解不加解密 return false; } //获取属性注解 Field[] fields = clazz.getDeclaredFields(); return Arrays.stream(fields).anyMatch(field -> field.isAnnotationPresent(CryptAnnotation.class)); }} 三、注解
import com.sfpay.merchant.common.constant.EncryptDataTypeEnum; import java.lang.annotation.*; /** * @author *** * @Date 2020/12/30 20:13 * @description 加密注解类 * @Param * @return **/@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.FIELD, ElementType.TYPE})@Documented@Inheritedpublic @interface CryptAnnotation { EncryptDataTypeEnum type() default EncryptDataTypeEnum.OTHER;}cryptService 为加密服务,怎么实现自己可以根据实际情况来实现。
到此,相信大家对"mybatis-plus拦截器敏感字段加解密的实现方法是什么"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
参数
注解
方法
拦截器
字段
数据
查询
类型
加密
场景
属性
报文
对象
结果
更新
内容
名称
备份
实际
数据库
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
中智农互联网科技
亿人帮互联网科技有限公司
哈尔滨大商圈互联网科技有限公司
科技平台互联网
科技制造互联网公司
中国 科技 互联网
安徽鑫晟辉互联网科技
苏州互联网科技贷款公司
科技互联网公司logo
人人互联网科技是培训
互联网科技生活的内容
科技大学互联网专业好不好
互联网公司会议桌创意科技软装饰
安控科技rtu产品工业互联网
广州优美互联网科技
互联网企业和科技型企业
互联网金融科技公司干啥的
上海科技产业互联网平台
互联网领先科技活动
知域互联网科技有限公司官网
互联网和科技创新
万达互联网科技
互联网科技汛
互联网科技公司做什么
互联网科技公司需要的职位
互联网科技产品
企晟互联网信息科技有限公司
卓翼科技产业互联网合作
从那以后互联网科技有限公司
互联网科技包装股