diff --git a/huaheng-wms-core/src/main/java/org/jeecg/modules/desensitization/plugin/DesensitizationInterceptor.java b/huaheng-wms-core/src/main/java/org/jeecg/modules/desensitization/plugin/DesensitizationResultSetInterceptor.java index bdbd992..0c93dac 100644 --- a/huaheng-wms-core/src/main/java/org/jeecg/modules/desensitization/plugin/DesensitizationInterceptor.java +++ b/huaheng-wms-core/src/main/java/org/jeecg/modules/desensitization/plugin/DesensitizationResultSetInterceptor.java @@ -1,94 +1,61 @@ package org.jeecg.modules.desensitization.plugin; - -import cn.hutool.core.util.ObjectUtil; import org.apache.ibatis.executor.resultset.ResultSetHandler; import org.apache.ibatis.plugin.*; import org.apache.shiro.SecurityUtils; -import org.jeecg.common.exception.JeecgBootException; import org.jeecg.modules.desensitization.annotation.SensitiveField; import org.jeecg.modules.desensitization.enums.SensitiveTypeEnums; import org.jeecg.modules.desensitization.strategy.SensitiveContext; import org.jeecg.modules.desensitization.strategy.SensitiveStrategy; -import org.jeecg.modules.system.entity.SysUserRole; -import org.jeecg.modules.system.service.ISysRoleService; -import org.jeecg.utils.HuahengJwtUtil; import org.reflections.ReflectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.core.annotation.Order; -import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; -import javax.annotation.Resource; -import javax.servlet.http.HttpServletRequest; +import java.sql.Statement; import java.lang.reflect.Field; import java.util.*; import java.util.concurrent.ConcurrentHashMap; -import static org.jeecg.utils.HuahengJwtUtil.getRolesByToken; - - -/** - * 基于拦截器对数据脱敏 - * - * @author xub - * @date 2022/6/2 下午2:23 - */ @Intercepts({ - @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {java.sql.Statement.class}) + @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class}) }) -@Service -@Order(-1) -public class DesensitizationInterceptor implements Interceptor { - +public class DesensitizationResultSetInterceptor implements Interceptor { - private static final Logger log = LoggerFactory.getLogger(DesensitizationInterceptor.class); + private static final Logger log = LoggerFactory.getLogger(DesensitizationResultSetInterceptor.class); - /** - * key值为class对象 value可以理解成是该类带有SensitiveField注解的属性,只不过对属性封装了一层。 - * 它是非常能够提高性能的处理器 它的作用就是不用每一次一个对象经来都要看下它的哪些属性带有SensitiveField注解 - * 毕竟类的反射在性能上并不友好。只要key包含该对象那就不需要检查它哪些属性带SensitiveField注解。 - */ - private Map<Class, List<Handler>> handlerMap = new ConcurrentHashMap<>(); + private final Map<Class<?>, List<Handler>> handlerMap = new ConcurrentHashMap<>(); @Override public Object intercept(Invocation invocation) throws Throwable { - // 获取结果 - List<Object> results = (List<Object>) invocation.proceed(); - if (CollectionUtils.isEmpty(results)) { - return results; - } - // 批量设置加密 - for (Object object : results) { - process(object); + Object result = invocation.proceed(); + + // 仅对查询结果集进行脱敏处理 + if (result instanceof List) { + List<?> results = (List<?>) result; + for (Object object : results) { + process(object); + } } - return results; + return result; } - private void process(Object object) throws Throwable { - if(ObjectUtil.isNotEmpty(object)){ - Class handlerKey = object.getClass(); + if (object != null) { + Class<?> handlerKey = object.getClass(); List<Handler> handlerList = handlerMap.get(handlerKey); - //性能优化点,如果有两个都是user对象同时,那么只需有个进行反射处理属性就好了,另一个只需执行下面的for循环 - SYNC: if (handlerList == null) { synchronized (this) { handlerList = handlerMap.get(handlerKey); - //如果到这里map集合已经存在,则跳出到指定SYNC标签 - if (handlerList != null) { - break SYNC; - } - handlerMap.put(handlerKey, handlerList = new ArrayList<>()); - // 反射工具类 获取带有SensitiveField注解的所有属性字段 - Set<Field> allFields = ReflectionUtils.getAllFields( - object.getClass(), - input -> input != null && input.getAnnotation(SensitiveField.class) != null - ); - - for (Field field : allFields) { - handlerList.add(new Handler(field)); + if (handlerList == null) { + handlerList = new ArrayList<>(); + Set<Field> allFields = ReflectionUtils.getAllFields( + object.getClass(), + input -> input != null && input.getAnnotation(SensitiveField.class) != null + ); + for (Field field : allFields) { + handlerList.add(new Handler(field)); + } + handlerMap.put(handlerKey, handlerList); } } } @@ -96,10 +63,8 @@ public class DesensitizationInterceptor implements Interceptor { handler.accept(object); } } - } - @Override public Object plugin(Object target) { return Plugin.wrap(target, this); @@ -109,35 +74,35 @@ public class DesensitizationInterceptor implements Interceptor { public void setProperties(Properties properties) { } - private static class Handler { - Field field; + private final Field field; + private final SensitiveTypeEnums typeEnums; + private final String fillValue; + private final SensitiveStrategy sensitiveStrategy; Handler(Field field) { this.field = field; + SensitiveField annotation = field.getAnnotation(SensitiveField.class); + this.typeEnums = annotation.value(); + this.fillValue = annotation.fillValue(); + this.sensitiveStrategy = SensitiveContext.get(typeEnums); } - private boolean checkField(Object object, Field field) throws IllegalAccessException { + private boolean checkField(Object object) throws IllegalAccessException { if (!field.isAccessible()) { field.setAccessible(true); } - //如果为空 那么就不用进行脱敏操作了 return field.get(object) != null; } public void accept(Object o) throws Throwable { - if (checkField(o, field)) { - SensitiveField annotation = field.getAnnotation(SensitiveField.class); - SensitiveTypeEnums typeEnums = annotation.value(); - String fillValue = annotation.fillValue(); - Object o1 = field.get(o); - if(!SecurityUtils.getSubject().hasRole("desensitization")){ - SensitiveStrategy sensitiveStrategy = SensitiveContext.get(typeEnums); - String s = sensitiveStrategy.handle(o1, fillValue); - field.set(o, s); + if (checkField(o)) { + if (!SecurityUtils.getSubject().hasRole("desensitization")) { + Object fieldValue = field.get(o); + String maskedValue = sensitiveStrategy.handle(fieldValue, fillValue); + field.set(o, maskedValue); } } } } - } diff --git a/huaheng-wms-core/src/main/java/org/jeecg/modules/desensitization/plugin/MyBatisUpdateInterceptor.java b/huaheng-wms-core/src/main/java/org/jeecg/modules/desensitization/plugin/MyBatisUpdateInterceptor.java new file mode 100644 index 0000000..b618879 --- /dev/null +++ b/huaheng-wms-core/src/main/java/org/jeecg/modules/desensitization/plugin/MyBatisUpdateInterceptor.java @@ -0,0 +1,37 @@ +package org.jeecg.modules.desensitization.plugin; + +import org.apache.ibatis.executor.Executor; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.plugin.*; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Service; + +import java.util.Properties; + +@Intercepts({ + @Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}) +}) +@Service +@Order(-1) +public class MyBatisUpdateInterceptor implements Interceptor { + + + private static final Logger log = LoggerFactory.getLogger(MyBatisUpdateInterceptor.class); + + @Override + public Object intercept(Invocation invocation) throws Throwable { + // 在这里处理插入/更新/删除前后的操作 + return invocation.proceed(); + } + + @Override + public Object plugin(Object target) { + return Plugin.wrap(target, this); + } + + @Override + public void setProperties(Properties properties) { + } +} diff --git a/huaheng-wms-core/src/main/java/org/jeecg/modules/system/entity/SysUser.java b/huaheng-wms-core/src/main/java/org/jeecg/modules/system/entity/SysUser.java index 4ddd5c6..c42d435 100644 --- a/huaheng-wms-core/src/main/java/org/jeecg/modules/system/entity/SysUser.java +++ b/huaheng-wms-core/src/main/java/org/jeecg/modules/system/entity/SysUser.java @@ -47,7 +47,7 @@ public class SysUser implements Serializable { * 登录账号 */ @Excel(name = "登录账号", width = 15) -// @SensitiveField(SensitiveTypeEnums.CHINESE_NAME) + @SensitiveField(SensitiveTypeEnums.CHINESE_NAME) private String username; /** diff --git a/huaheng-wms-core/src/main/resources/mybatis-config.xml b/huaheng-wms-core/src/main/resources/mybatis-config.xml new file mode 100644 index 0000000..7610273 --- /dev/null +++ b/huaheng-wms-core/src/main/resources/mybatis-config.xml @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" + "http://mybatis.org/dtd/mybatis-3-config.dtd"> +<configuration> + + <!-- 其他 MyBatis 配置 --> + + <plugins> + <!-- 配置查询操作的脱敏拦截器 --> + <plugin interceptor="org.jeecg.modules.desensitization.plugin.DesensitizationResultSetInterceptor"/> + <!-- 配置插入、更新、删除操作的拦截器 --> + <plugin interceptor="org.jeecg.modules.desensitization.plugin.MyBatisUpdateInterceptor"/> + </plugins> + + <!-- 其他 MyBatis 配置 --> + +</configuration>