Browse Source

feat(ext/plugins): 数据权限拦截器增加SQL多表场景支持

HouKunLin 3 năm trước cách đây
mục cha
commit
0c483949a7

+ 1 - 1
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/handler/DataPermissionHandler.java

@@ -30,7 +30,7 @@ public interface DataPermissionHandler {
      *
      * @param where             待执行 SQL Where 条件表达式
      * @param mappedStatementId Mybatis MappedStatement Id 根据该参数可以判断具体执行方法
-     * @return JSqlParser 条件表达式
+     * @return JSqlParser 条件表达式,返回的条件表达式会覆盖原有的条件表达式
      */
     Expression getSqlSegment(Expression where, String mappedStatementId);
 }

+ 50 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/handler/MultiDataPermissionHandler.java

@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2011-2022, baomidou (jobob@qq.com).
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.baomidou.mybatisplus.extension.plugins.handler;
+
+import net.sf.jsqlparser.expression.Expression;
+import net.sf.jsqlparser.schema.Table;
+
+/**
+ * 支持多表的数据权限处理器
+ *
+ * @author houkunlin
+ * @since 3.5.2 +
+ */
+public interface MultiDataPermissionHandler extends DataPermissionHandler {
+    /**
+     * 为兼容旧版数据权限处理器,继承了 {@link DataPermissionHandler} 但是新的多表数据权限处理又不会调用此方法,因此标记过时
+     *
+     * @param where             待执行 SQL Where 条件表达式
+     * @param mappedStatementId Mybatis MappedStatement Id 根据该参数可以判断具体执行方法
+     * @return JSqlParser 条件表达式
+     * @deprecated 新的多表数据权限处理不会调用此方法,因此标记过时
+     */
+    @Deprecated
+    @Override
+    default Expression getSqlSegment(Expression where, String mappedStatementId) {
+        return where;
+    }
+
+    /**
+     * 获取数据权限 SQL 片段
+     *
+     * @param table             所执行的数据库表信息,可以通过此参数获取表名和表别名
+     * @param mappedStatementId Mybatis MappedStatement Id 根据该参数可以判断具体执行方法
+     * @return JSqlParser 条件表达式,返回的条件表达式会拼接在原有的表达式后面(不会覆盖原有的表达式)
+     */
+    Expression getSqlSegment(final Table table, final String mappedStatementId);
+}

+ 54 - 5
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DataPermissionInterceptor.java

@@ -17,14 +17,17 @@ package com.baomidou.mybatisplus.extension.plugins.inner;
 
 import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
 import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
-import com.baomidou.mybatisplus.extension.parser.JsqlParserSupport;
 import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler;
+import com.baomidou.mybatisplus.extension.plugins.handler.MultiDataPermissionHandler;
 import lombok.*;
 import net.sf.jsqlparser.expression.Expression;
+import net.sf.jsqlparser.schema.Table;
+import net.sf.jsqlparser.statement.delete.Delete;
 import net.sf.jsqlparser.statement.select.PlainSelect;
 import net.sf.jsqlparser.statement.select.Select;
 import net.sf.jsqlparser.statement.select.SelectBody;
 import net.sf.jsqlparser.statement.select.SetOperationList;
+import net.sf.jsqlparser.statement.update.Update;
 import org.apache.ibatis.executor.Executor;
 import org.apache.ibatis.mapping.BoundSql;
 import org.apache.ibatis.mapping.MappedStatement;
@@ -38,7 +41,7 @@ import java.util.List;
  * 数据权限处理器
  *
  * @author hubin
- * @since 3.4.1 +
+ * @since 3.5.2
  */
 @Data
 @NoArgsConstructor
@@ -46,12 +49,14 @@ import java.util.List;
 @ToString(callSuper = true)
 @EqualsAndHashCode(callSuper = true)
 @SuppressWarnings({"rawtypes"})
-public class DataPermissionInterceptor extends JsqlParserSupport implements InnerInterceptor {
+public class DataPermissionInterceptor extends BaseMultiTableInnerInterceptor implements InnerInterceptor {
     private DataPermissionHandler dataPermissionHandler;
 
     @Override
     public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
-        if (InterceptorIgnoreHelper.willIgnoreDataPermission(ms.getId())) return;
+        if (InterceptorIgnoreHelper.willIgnoreDataPermission(ms.getId())) {
+            return;
+        }
         PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
         mpBs.sql(parserSingle(mpBs.sql(), ms.getId()));
     }
@@ -75,9 +80,53 @@ public class DataPermissionInterceptor extends JsqlParserSupport implements Inne
      * @param whereSegment 查询条件片段
      */
     protected void setWhere(PlainSelect plainSelect, String whereSegment) {
-        Expression sqlSegment = dataPermissionHandler.getSqlSegment(plainSelect.getWhere(), whereSegment);
+        if (dataPermissionHandler instanceof MultiDataPermissionHandler) {
+            processPlainSelect(plainSelect, whereSegment);
+            return;
+        }
+        // 兼容旧版的数据权限处理
+        final Expression sqlSegment = dataPermissionHandler.getSqlSegment(plainSelect.getWhere(), whereSegment);
         if (null != sqlSegment) {
             plainSelect.setWhere(sqlSegment);
         }
     }
+
+    /**
+     * update 语句处理
+     */
+    @Override
+    protected void processUpdate(Update update, int index, String sql, Object obj) {
+        final Expression sqlSegment = getUpdateOrDeleteExpression(update.getTable(), update.getWhere(), (String) obj);
+        if (null != sqlSegment) {
+            update.setWhere(sqlSegment);
+        }
+    }
+
+
+    /**
+     * delete 语句处理
+     */
+    @Override
+    protected void processDelete(Delete delete, int index, String sql, Object obj) {
+        final Expression sqlSegment = getUpdateOrDeleteExpression(delete.getTable(), delete.getWhere(), (String) obj);
+        if (null != sqlSegment) {
+            delete.setWhere(sqlSegment);
+        }
+    }
+
+    protected Expression getUpdateOrDeleteExpression(final Table table, final Expression where, final String whereSegment) {
+        if (dataPermissionHandler instanceof MultiDataPermissionHandler) {
+            return andExpression(table, where, whereSegment);
+        } else {
+            // 兼容旧版的数据权限处理
+            return dataPermissionHandler.getSqlSegment(where, whereSegment);
+        }
+    }
+
+    @Override
+    public Expression buildTableExpression(final Table table, final String whereSegment) {
+        // 只有新版数据权限处理器才会执行到这里
+        final MultiDataPermissionHandler handler = (MultiDataPermissionHandler) dataPermissionHandler;
+        return handler.getSqlSegment(table, whereSegment);
+    }
 }