miemie 4 years ago
parent
commit
7a5c344a73

+ 44 - 0
mybatis-plus-annotation/src/main/java/com/baomidou/mybatisplus/annotation/InterceptorIgnore.java

@@ -0,0 +1,44 @@
+package com.baomidou.mybatisplus.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 内置插件的一些过滤规则
+ * <p>
+ * 支持注解在 mapper 上以及 mapper.method 上
+ * 同时存在则 mapper.method 比 mapper 优先级高
+ * 各属性返回 false 表示不走插件(在配置了插件的情况下)
+ *
+ * @author miemie
+ * @since 2020-07-31
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface InterceptorIgnore {
+
+    /**
+     * 行级租户 {@link com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor}
+     */
+    String tenantLine() default "";
+
+    /**
+     * 动态表名 {@link com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor}
+     */
+    String dynamicTableName() default "";
+
+    /**
+     * 攻击 SQL 阻断解析器,防止全表更新与删除 {@link com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor}
+     */
+    String blockAttack() default "";
+
+    /**
+     * 垃圾SQL拦截 {@link com.baomidou.mybatisplus.extension.plugins.inner.IllegalSQLInnerInterceptor}
+     */
+    String illegalSql() default "";
+
+    /**
+     * 非mp提供的 {@link com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor}
+     */
+    String[] additional() default {};
+}

+ 91 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/plugins/InterceptorIgnoreHelper.java

@@ -0,0 +1,91 @@
+package com.baomidou.mybatisplus.core.plugins;
+
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
+import com.baomidou.mybatisplus.core.toolkit.ArrayUtils;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Function;
+
+/**
+ * @author miemie
+ * @since 2020-07-31
+ */
+public class InterceptorIgnoreHelper {
+
+    /**
+     * SQL 解析缓存
+     * key 可能是 mappedStatement 的 ID,也可能是 class 的 name
+     */
+    private static final Map<String, InterceptorIgnoreCache> INTERCEPTOR_IGNORE_CACHE = new ConcurrentHashMap<>();
+
+    /**
+     * 初始化缓存 接口上 InterceptorIgnore 注解信息
+     *
+     * @param mapperClass Mapper Class
+     */
+    public synchronized static void initSqlParserInfoCache(Class<?> mapperClass) {
+        InterceptorIgnore ignore = mapperClass.getAnnotation(InterceptorIgnore.class);
+        if (ignore != null) {
+            INTERCEPTOR_IGNORE_CACHE.put(mapperClass.getName(), buildInterceptorIgnoreCache(ignore));
+        }
+    }
+
+    /**
+     * 初始化缓存 方法上 InterceptorIgnore 注解信息
+     *
+     * @param mapperClassName Mapper Class Name
+     * @param method          Method
+     */
+    public static void initSqlParserInfoCache(String mapperClassName, Method method) {
+        InterceptorIgnore ignore = method.getAnnotation(InterceptorIgnore.class);
+        if (ignore != null) {
+            INTERCEPTOR_IGNORE_CACHE.computeIfAbsent(mapperClassName.concat(StringPool.DOT).concat(method.getName()),
+                k -> buildInterceptorIgnoreCache(ignore));
+        }
+    }
+
+    public static boolean willIgnore(String id, Function<InterceptorIgnoreCache, Boolean> function) {
+        InterceptorIgnoreCache cache = INTERCEPTOR_IGNORE_CACHE.get(id);
+        if (cache == null) {
+            id = id.substring(0, id.lastIndexOf(StringPool.DOT));
+            cache = INTERCEPTOR_IGNORE_CACHE.get(id);
+        }
+        if (cache != null) {
+            return function.apply(cache);
+        }
+        return false;
+    }
+
+    private static InterceptorIgnoreCache buildInterceptorIgnoreCache(InterceptorIgnore ignore) {
+        String tenantLine = ignore.tenantLine();
+        String dynamicTableName = ignore.dynamicTableName();
+        String blockAttack = ignore.blockAttack();
+        String illegalSql = ignore.illegalSql();
+        String[] additional = ignore.additional();
+        return new InterceptorIgnoreCache(StringUtils.isBlank(tenantLine) ? null : Boolean.valueOf(tenantLine),
+            StringUtils.isBlank(dynamicTableName) ? null : Boolean.valueOf(dynamicTableName),
+            StringUtils.isBlank(blockAttack) ? null : Boolean.valueOf(blockAttack),
+            StringUtils.isBlank(illegalSql) ? null : Boolean.valueOf(illegalSql),
+            ArrayUtils.isEmpty(additional) ? Collections.emptyList() : Arrays.asList(additional)
+        );
+    }
+
+    @Data
+    @AllArgsConstructor
+    public static class InterceptorIgnoreCache {
+        private Boolean tenantLine;
+        private Boolean dynamicTableName;
+        private Boolean blockAttack;
+        private Boolean illegalSql;
+        private List<String> additional;
+    }
+}

+ 9 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/BlockAttackInnerInterceptor.java

@@ -15,6 +15,7 @@
  */
  */
 package com.baomidou.mybatisplus.extension.plugins.inner;
 package com.baomidou.mybatisplus.extension.plugins.inner;
 
 
+import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
 import com.baomidou.mybatisplus.core.toolkit.Assert;
 import com.baomidou.mybatisplus.core.toolkit.Assert;
 import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
 import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
 import com.baomidou.mybatisplus.extension.parser.JsqlParserSupport;
 import com.baomidou.mybatisplus.extension.parser.JsqlParserSupport;
@@ -41,6 +42,7 @@ public class BlockAttackInnerInterceptor extends JsqlParserSupport implements In
         MappedStatement ms = handler.mappedStatement();
         MappedStatement ms = handler.mappedStatement();
         SqlCommandType sct = ms.getSqlCommandType();
         SqlCommandType sct = ms.getSqlCommandType();
         if (sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) {
         if (sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) {
+            if (ignore(ms)) return;
             BoundSql boundSql = handler.boundSql();
             BoundSql boundSql = handler.boundSql();
             parserMulti(boundSql.getSql(), null);
             parserMulti(boundSql.getSql(), null);
         }
         }
@@ -55,4 +57,11 @@ public class BlockAttackInnerInterceptor extends JsqlParserSupport implements In
     protected void processUpdate(Update update, int index, Object obj) {
     protected void processUpdate(Update update, int index, Object obj) {
         Assert.notNull(update.getWhere(), "Prohibition of table update operation");
         Assert.notNull(update.getWhere(), "Prohibition of table update operation");
     }
     }
+
+    public boolean ignore(MappedStatement ms) {
+        return InterceptorIgnoreHelper.willIgnore(ms.getId(), i -> {
+            Boolean blockAttack = i.getBlockAttack();
+            return blockAttack != null && blockAttack;
+        });
+    }
 }
 }

+ 10 - 0
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/DynamicTableNameInnerInterceptor.java

@@ -15,6 +15,7 @@
  */
  */
 package com.baomidou.mybatisplus.extension.plugins.inner;
 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.core.toolkit.PluginUtils;
 import com.baomidou.mybatisplus.core.toolkit.TableNameParser;
 import com.baomidou.mybatisplus.core.toolkit.TableNameParser;
 import com.baomidou.mybatisplus.extension.plugins.handler.TableNameHandler;
 import com.baomidou.mybatisplus.extension.plugins.handler.TableNameHandler;
@@ -52,6 +53,7 @@ public class DynamicTableNameInnerInterceptor implements InnerInterceptor {
     @Override
     @Override
     public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
     public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
         PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
         PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
+        if (ignore(ms)) return;
         mpBs.sql(this.changeTable(mpBs.sql()));
         mpBs.sql(this.changeTable(mpBs.sql()));
     }
     }
 
 
@@ -61,6 +63,7 @@ public class DynamicTableNameInnerInterceptor implements InnerInterceptor {
         MappedStatement ms = mpSh.mappedStatement();
         MappedStatement ms = mpSh.mappedStatement();
         SqlCommandType sct = ms.getSqlCommandType();
         SqlCommandType sct = ms.getSqlCommandType();
         if (sct == SqlCommandType.INSERT || sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) {
         if (sct == SqlCommandType.INSERT || sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) {
+            if (ignore(ms)) return;
             PluginUtils.MPBoundSql mpBs = mpSh.mPBoundSql();
             PluginUtils.MPBoundSql mpBs = mpSh.mPBoundSql();
             mpBs.sql(this.changeTable(mpBs.sql()));
             mpBs.sql(this.changeTable(mpBs.sql()));
         }
         }
@@ -91,4 +94,11 @@ public class DynamicTableNameInnerInterceptor implements InnerInterceptor {
         }
         }
         return builder.toString();
         return builder.toString();
     }
     }
+
+    public boolean ignore(MappedStatement ms) {
+        return InterceptorIgnoreHelper.willIgnore(ms.getId(), i -> {
+            Boolean dynamicTableName = i.getDynamicTableName();
+            return dynamicTableName != null && dynamicTableName;
+        });
+    }
 }
 }

+ 10 - 3
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/IllegalSQLInnerInterceptor.java

@@ -17,6 +17,7 @@ package com.baomidou.mybatisplus.extension.plugins.inner;
 
 
 import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
 import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
 import com.baomidou.mybatisplus.core.parser.SqlParserHelper;
 import com.baomidou.mybatisplus.core.parser.SqlParserHelper;
+import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
 import com.baomidou.mybatisplus.core.toolkit.Assert;
 import com.baomidou.mybatisplus.core.toolkit.Assert;
 import com.baomidou.mybatisplus.core.toolkit.EncryptUtils;
 import com.baomidou.mybatisplus.core.toolkit.EncryptUtils;
 import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
 import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
@@ -92,9 +93,8 @@ public class IllegalSQLInnerInterceptor extends JsqlParserSupport implements Inn
         PluginUtils.MPStatementHandler mpStatementHandler = PluginUtils.mpStatementHandler(sh);
         PluginUtils.MPStatementHandler mpStatementHandler = PluginUtils.mpStatementHandler(sh);
         MappedStatement ms = mpStatementHandler.mappedStatement();
         MappedStatement ms = mpStatementHandler.mappedStatement();
         SqlCommandType sct = ms.getSqlCommandType();
         SqlCommandType sct = ms.getSqlCommandType();
-        if (sct == SqlCommandType.INSERT || SqlParserHelper.getSqlParserInfo(ms)) {
-            return;
-        }
+        if (sct == SqlCommandType.INSERT || SqlParserHelper.getSqlParserInfo(ms)) return;
+        if (ignore(ms)) return;
         BoundSql boundSql = mpStatementHandler.boundSql();
         BoundSql boundSql = mpStatementHandler.boundSql();
         String originalSql = boundSql.getSql();
         String originalSql = boundSql.getSql();
         logger.debug("检查SQL是否合规,SQL:" + originalSql);
         logger.debug("检查SQL是否合规,SQL:" + originalSql);
@@ -335,6 +335,13 @@ public class IllegalSQLInnerInterceptor extends JsqlParserSupport implements Inn
         return indexInfos;
         return indexInfos;
     }
     }
 
 
+    public boolean ignore(MappedStatement ms) {
+        return InterceptorIgnoreHelper.willIgnore(ms.getId(), i -> {
+            Boolean illegalSql = i.getIllegalSql();
+            return illegalSql != null && illegalSql;
+        });
+    }
+
     /**
     /**
      * 索引对象
      * 索引对象
      */
      */

+ 12 - 6
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/TenantLineInnerInterceptor.java

@@ -16,6 +16,7 @@
 package com.baomidou.mybatisplus.extension.plugins.inner;
 package com.baomidou.mybatisplus.extension.plugins.inner;
 
 
 import com.baomidou.mybatisplus.core.parser.SqlParserHelper;
 import com.baomidou.mybatisplus.core.parser.SqlParserHelper;
+import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
 import com.baomidou.mybatisplus.core.toolkit.*;
 import com.baomidou.mybatisplus.core.toolkit.*;
 import com.baomidou.mybatisplus.extension.parser.JsqlParserSupport;
 import com.baomidou.mybatisplus.extension.parser.JsqlParserSupport;
 import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
 import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
@@ -62,9 +63,8 @@ public class TenantLineInnerInterceptor extends JsqlParserSupport implements Inn
 
 
     @Override
     @Override
     public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
     public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
-        if (SqlParserHelper.getSqlParserInfo(ms)) {
-            return;
-        }
+        if (ignore(ms)) return;
+        if (SqlParserHelper.getSqlParserInfo(ms)) return;
         PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
         PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
         mpBs.sql(parserSingle(mpBs.sql(), null));
         mpBs.sql(parserSingle(mpBs.sql(), null));
     }
     }
@@ -73,11 +73,10 @@ public class TenantLineInnerInterceptor extends JsqlParserSupport implements Inn
     public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
     public void beforePrepare(StatementHandler sh, Connection connection, Integer transactionTimeout) {
         PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh);
         PluginUtils.MPStatementHandler mpSh = PluginUtils.mpStatementHandler(sh);
         MappedStatement ms = mpSh.mappedStatement();
         MappedStatement ms = mpSh.mappedStatement();
-        if (SqlParserHelper.getSqlParserInfo(ms)) {
-            return;
-        }
         SqlCommandType sct = ms.getSqlCommandType();
         SqlCommandType sct = ms.getSqlCommandType();
         if (sct == SqlCommandType.INSERT || sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) {
         if (sct == SqlCommandType.INSERT || sct == SqlCommandType.UPDATE || sct == SqlCommandType.DELETE) {
+            if (ignore(ms)) return;
+            if (SqlParserHelper.getSqlParserInfo(ms)) return;
             PluginUtils.MPBoundSql mpBs = mpSh.mPBoundSql();
             PluginUtils.MPBoundSql mpBs = mpSh.mPBoundSql();
             mpBs.sql(parserMulti(mpBs.sql(), null));
             mpBs.sql(parserMulti(mpBs.sql(), null));
         }
         }
@@ -343,6 +342,13 @@ public class TenantLineInnerInterceptor extends JsqlParserSupport implements Inn
         return new Column(column.toString());
         return new Column(column.toString());
     }
     }
 
 
+    public boolean ignore(MappedStatement ms) {
+        return InterceptorIgnoreHelper.willIgnore(ms.getId(), i -> {
+            Boolean tenantLine = i.getTenantLine();
+            return tenantLine != null && tenantLine;
+        });
+    }
+
     @Override
     @Override
     public void setProperties(Properties properties) {
     public void setProperties(Properties properties) {
         PropertyMapper.newInstance(properties)
         PropertyMapper.newInstance(properties)