فهرست منبع

pms 设备责任人数据权限增强 在原有的数据权限上拼接 设备责任人数据权限规则 排查重复生成查询语句的错误...

zhangcl 1 هفته پیش
والد
کامیت
363f7dd284

+ 25 - 1
yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/config/YudaoDataPermissionAutoConfiguration.java

@@ -12,7 +12,10 @@ import cn.iocoder.yudao.framework.datapermission.core.rule.dept.DeptDataPermissi
 import cn.iocoder.yudao.framework.datapermission.core.rule.device.DevicePersonDataPermissionRule;
 import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
 import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler;
 import com.baomidou.mybatisplus.extension.plugins.inner.DataPermissionInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.ObjectProvider;
 import org.springframework.boot.autoconfigure.AutoConfiguration;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -26,6 +29,7 @@ import java.util.List;
  * @author 芋道源码
  */
 @AutoConfiguration
+@Slf4j
 public class YudaoDataPermissionAutoConfiguration {
 
     @Bean
@@ -66,7 +70,27 @@ public class YudaoDataPermissionAutoConfiguration {
         DataPermissionInterceptor inner = new DataPermissionInterceptor(handler);
         // 添加到 interceptor 中
         // 需要加在首个,主要是为了在分页插件前面。这个是 MyBatis Plus 的规定
-        MyBatisUtils.addInterceptor(interceptor, inner, 0);
+        // ========== 避免重复添加拦截器 ==========
+        boolean alreadyAdded = false;
+        for (InnerInterceptor existing : interceptor.getInterceptors()) {
+            if (existing instanceof DataPermissionInterceptor) {
+                DataPermissionHandler existingHandler =
+                        ((DataPermissionInterceptor) existing).getDataPermissionHandler();
+                if (existingHandler instanceof DataPermissionRuleHandler) {
+                    alreadyAdded = true;
+                    break;
+                }
+            }
+        }
+
+        if (!alreadyAdded) {
+            // 添加到 interceptor 中
+            // 需要加在首个,主要是为了在分页插件前面。这个是 MyBatis Plus 的规定
+            MyBatisUtils.addInterceptor(interceptor, inner, 0);
+            log.info("[DataPermission] 添加数据权限拦截器");
+        } else {
+            log.warn("[DataPermission] 数据权限拦截器已存在,跳过重复添加");
+        }
         return handler;
     }
 

+ 47 - 3
yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/db/DataPermissionRuleHandler.java

@@ -11,6 +11,7 @@ import net.sf.jsqlparser.expression.Alias;
 import net.sf.jsqlparser.expression.Expression;
 import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
 import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
+import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
 import net.sf.jsqlparser.schema.Table;
 
 import java.util.List;
@@ -31,6 +32,10 @@ public class DataPermissionRuleHandler implements MultiDataPermissionHandler {
 
     @Override
     public Expression getSqlSegment(Table table, Expression where, String mappedStatementId) {
+        // 打印当前线程和 MappedStatement 用于调试重复调用问题
+        log.debug("[DataPermission] 线程: {} 处理: {}",
+                Thread.currentThread().getName(), mappedStatementId);
+
         // 获得 Mapper 对应的数据权限的规则
         List<DataPermissionRule> rules = ruleFactory.getDataPermissionRule(mappedStatementId);
 
@@ -52,8 +57,7 @@ public class DataPermissionRuleHandler implements MultiDataPermissionHandler {
         // 2. 生成条件表达式
         String tableName = MyBatisUtils.getTableName(table);
 
-        log.debug("[DataPermission] MappedStatement: {}, Table: {}, Rules count: {}",
-                mappedStatementId, tableName, rules.size());
+        log.debug("[DataPermission] 开始处理数据权限: MappedStatement={}, Table={}", mappedStatementId, tableName);
 
         Expression permissionExpression = buildPermissionExpression(tableName, table.getAlias(), rules);
 
@@ -62,9 +66,49 @@ public class DataPermissionRuleHandler implements MultiDataPermissionHandler {
             return where;
         }
 
-        return where == null ? permissionExpression
+        // 避免重复添加逻辑删除条件
+        if (where != null) {
+            log.debug("[DataPermission] 原始 WHERE 条件: {}", where.toString());
+            // 检查原始条件是否已包含逻辑删除条件(deleted = 0)
+            if (containsDeletedCondition(where)) {
+                // 只添加权限表达式,避免重复
+                return new AndExpression(where, permissionExpression);
+            }
+        } else {
+            log.debug("[DataPermission] 原始 WHERE 条件为空");
+        }
+
+        log.debug("[DataPermission] 权限表达式: {}", permissionExpression.toString());
+
+        Expression result = where == null ? permissionExpression
                 : new AndExpression(where, permissionExpression);
+        log.debug("[DataPermission] 最终 WHERE 条件: {}", result != null ? result.toString() : "null");
+        return result;
+
+    }
 
+    /**
+     * 检查表达式是否包含逻辑删除条件(deleted = 0)
+     */
+    private boolean containsDeletedCondition(Expression expression) {
+        if (expression instanceof EqualsTo) {
+            EqualsTo equalsTo = (EqualsTo) expression;
+            String left = equalsTo.getLeftExpression().toString();
+            String right = equalsTo.getRightExpression().toString();
+            // 更宽松的匹配逻辑
+            if (left.toLowerCase().contains("deleted") && "0".equals(right)) {
+                return true;
+            }
+        } else if (expression instanceof AndExpression) {
+            AndExpression and = (AndExpression) expression;
+            return containsDeletedCondition(and.getLeftExpression()) ||
+                    containsDeletedCondition(and.getRightExpression());
+        } else if (expression instanceof OrExpression) {
+            OrExpression or = (OrExpression) expression;
+            return containsDeletedCondition(or.getLeftExpression()) ||
+                    containsDeletedCondition(or.getRightExpression());
+        }
+        return false;
     }
 
     private Expression buildPermissionExpression(String tableName, Alias tableAlias,

+ 9 - 1
yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/CombinedDataPermissionRuleFactory.java

@@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.datapermission.core.config.DevicePermissionCon
 import cn.iocoder.yudao.framework.datapermission.core.rule.dept.DeptDataPermissionRule;
 import cn.iocoder.yudao.framework.datapermission.core.rule.device.DevicePersonDataPermissionRule;
 import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
+import lombok.extern.slf4j.Slf4j;
 import net.sf.jsqlparser.expression.Alias;
 import net.sf.jsqlparser.expression.Expression;
 import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
@@ -21,6 +22,7 @@ import java.util.Set;
  *
  * @author ruiqi
  */
+@Slf4j
 public class CombinedDataPermissionRuleFactory extends DataPermissionRuleFactoryImpl {
 
     private final DeptDataPermissionRule deptRule;
@@ -45,7 +47,7 @@ public class CombinedDataPermissionRuleFactory extends DataPermissionRuleFactory
     public List<DataPermissionRule> getDataPermissionRule(String mappedStatementId) {
         List<DataPermissionRule> rules = super.getDataPermissionRule(mappedStatementId);
 
-        // 关键修改:只在需要组合规则的表上应用设备规则
+        // 只在需要组合规则的表上应用设备规则
         if (shouldApplyCombinedRule(mappedStatementId)) {
             return combineRules(rules);
         } else {
@@ -107,6 +109,7 @@ public class CombinedDataPermissionRuleFactory extends DataPermissionRuleFactory
         }
 
         String tableName = MyBatisUtils.getTableName(mappedStatementId);
+        log.debug("[RuleFactory] 处理 MappedStatement: {}, Table: {}", mappedStatementId, tableName);
         return tableName != null && combinedConfig.isCombinedTable(tableName);
     }
 
@@ -189,6 +192,11 @@ public class CombinedDataPermissionRuleFactory extends DataPermissionRuleFactory
             Expression deptExpr = deptRule != null ? deptRule.getExpression(tableName, tableAlias) : null;
             Expression deviceExpr = deviceRule != null ? deviceRule.getExpression(tableName, tableAlias) : null;
 
+            // 避免重复添加条件
+            if (deptExpr == null && deviceExpr == null) {
+                return null;
+            }
+
             // 组合为OR关系
             if (deptExpr != null && deviceExpr != null) {
                 return new OrExpression(deptExpr, deviceExpr);

+ 7 - 0
yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/dept/DeptDataPermissionRule.java

@@ -89,6 +89,13 @@ public class DeptDataPermissionRule implements DataPermissionRule {
 
     @Override
     public Expression getExpression(String tableName, Alias tableAlias) {
+        log.debug("[DeptRule] 检查表: {}", tableName);
+        // 检查表是否配置了数据权限
+        if (!TABLE_NAMES.contains(tableName)) {
+            log.debug("[DeptRule] 表 {} 未配置数据权限,跳过", tableName);
+            return null;
+        }
+
         // 只有有登陆用户的情况下,才进行数据权限的处理
         LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
         if (loginUser == null) {

+ 6 - 5
yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/core/rule/device/DevicePersonDataPermissionRule.java

@@ -8,6 +8,7 @@ import cn.iocoder.yudao.framework.security.core.LoginUser;
 import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
 import cn.iocoder.yudao.module.pms.api.permission.DevicePersonPermissionApi;
 import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
+import lombok.Setter;
 import lombok.extern.slf4j.Slf4j;
 import net.sf.jsqlparser.expression.Alias;
 import net.sf.jsqlparser.expression.Expression;
@@ -35,6 +36,7 @@ public class DevicePersonDataPermissionRule implements DataPermissionRule {
     private final Map<String, TableConfig> tableConfigs = new ConcurrentHashMap<>();
 
     // 只对特定表生效
+    @Setter
     private Set<String> enabledTables = new HashSet<>();
 
     private final DevicePersonPermissionApi devicePersonService;
@@ -81,10 +83,6 @@ public class DevicePersonDataPermissionRule implements DataPermissionRule {
         return enabledTables;
     }
 
-    public void setEnabledTables(Set<String> enabledTables) {
-        this.enabledTables = enabledTables;
-    }
-
     @Override
     public Expression getExpression(String tableName, Alias tableAlias) {
 
@@ -105,7 +103,10 @@ public class DevicePersonDataPermissionRule implements DataPermissionRule {
 
         // 3. 获取当前用户负责的设备ID集合
         Set<Long> responsibleDeviceIds = getResponsibleDeviceIds(loginUser);
-        if (CollUtil.isEmpty(responsibleDeviceIds)) return null;
+        if (CollUtil.isEmpty(responsibleDeviceIds)) {
+            log.debug("[getExpression] 用户 {} 没有负责的设备", loginUser.getId());
+            return null;
+        }
 
         // 5. 构建主表关联条件(EXISTS子查询)
         return buildDataPermissionExpression(config, tableName, tableAlias, responsibleDeviceIds);