From 866ddaaaedfbb0f338ef16d5685ee277632977f5 Mon Sep 17 00:00:00 2001 From: wenshao Date: Mon, 8 Apr 2013 12:54:16 +0800 Subject: [PATCH] improve wall filter --- .../druid/stat/DruidStatManagerFacade.java | 20 +++++++++++++++++ .../alibaba/druid/stat/DruidStatService.java | 1 + .../com/alibaba/druid/wall/WallConfig.java | 19 ++++++++++++++++ .../com/alibaba/druid/wall/WallProvider.java | 8 +++---- .../druid/wall/spi/MySqlWallVisitor.java | 6 +++++ .../druid/wall/spi/OracleWallVisitor.java | 11 ++++++++++ .../alibaba/druid/wall/spi/PGWallVisitor.java | 11 ++++++++++ .../druid/wall/spi/SQLServerWallVisitor.java | 11 ++++++++++ .../druid/wall/spi/WallVisitorUtils.java | 8 +++++++ .../druid/wall/mysql/permit-variant.txt | 3 ++- .../filter/wall/WallStatTest_blackList_1.java | 2 +- .../bvt/filter/wall/WallStatTest_statMap.java | 22 +++++++++++++++---- 12 files changed, 112 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java b/src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java index 718151aa94..57a3790e8b 100644 --- a/src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java +++ b/src/main/java/com/alibaba/druid/stat/DruidStatManagerFacade.java @@ -19,6 +19,7 @@ import java.lang.management.ManagementFactory; import java.sql.Driver; import java.sql.DriverManager; import java.util.ArrayList; +import java.util.Collection; import java.util.Date; import java.util.Enumeration; import java.util.HashMap; @@ -208,6 +209,25 @@ public final class DruidStatManagerFacade { newMap.put(key, valueB); } else if (valueB == null) { newMap.put(key, valueA); + } else if ("blackList".equals(key)) { + Set newSet = new HashSet(); + + Collection collectionA = (Collection) valueA; + for (String blackItem : collectionA) { + if (newSet.size() >= 500) { + break; + } + newSet.add(blackItem); + } + + Collection collectionB = (Collection) valueB; + for (String blackItem : collectionB) { + if (newSet.size() >= 50) { + break; + } + newSet.add(blackItem); + } + newMap.put(key, newSet); } else { if (valueA instanceof Map && valueB instanceof Map) { Object newValue = mergWallStat((Map)valueA, (Map)valueB); diff --git a/src/main/java/com/alibaba/druid/stat/DruidStatService.java b/src/main/java/com/alibaba/druid/stat/DruidStatService.java index ae554f6fa7..6dbf9ad4ba 100644 --- a/src/main/java/com/alibaba/druid/stat/DruidStatService.java +++ b/src/main/java/com/alibaba/druid/stat/DruidStatService.java @@ -267,6 +267,7 @@ public final class DruidStatService implements DruidStatServiceMBean { return sortedArray; } + @SuppressWarnings("unchecked") public Map getWallStatMap(Map parameters) { Integer dataSourceId = null; diff --git a/src/main/java/com/alibaba/druid/wall/WallConfig.java b/src/main/java/com/alibaba/druid/wall/WallConfig.java index de1b72d383..88fbc0b824 100644 --- a/src/main/java/com/alibaba/druid/wall/WallConfig.java +++ b/src/main/java/com/alibaba/druid/wall/WallConfig.java @@ -53,6 +53,8 @@ public class WallConfig implements WallConfigMBean { private boolean intersectAllow = false; private boolean replaceAllow = true; private boolean setAllow = true; + private boolean commitAllow = true; + private boolean useAllow = false; private boolean multiStatementAllow = false; @@ -104,6 +106,23 @@ public class WallConfig implements WallConfigMBean { public WallConfig(){ } + + public boolean isUseAllow() { + return useAllow; + } + + public void setUseAllow(boolean useAllow) { + this.useAllow = useAllow; + } + + + public boolean isCommitAllow() { + return commitAllow; + } + + public void setCommitAllow(boolean commitAllow) { + this.commitAllow = commitAllow; + } public boolean isIntersectAllow() { return intersectAllow; diff --git a/src/main/java/com/alibaba/druid/wall/WallProvider.java b/src/main/java/com/alibaba/druid/wall/WallProvider.java index 1c243367db..16dbe67a4b 100644 --- a/src/main/java/com/alibaba/druid/wall/WallProvider.java +++ b/src/main/java/com/alibaba/druid/wall/WallProvider.java @@ -46,11 +46,11 @@ public abstract class WallProvider { private int MAX_SQL_LENGTH = 2048; // 1k - private int whiteSqlMaxSize = 500; // 1k + private int whiteSqlMaxSize = 500; // 1k private LRUCache blackList; - private int blackSqlMaxSize = 500; // 1k + private int blackSqlMaxSize = 100; // 1k protected final WallConfig config; @@ -635,8 +635,8 @@ public abstract class WallProvider { } info.put("functions", functions); } - //info.put("whiteList", this.getWhiteList()); - //info.put("blackList", this.getBlackList()); + // info.put("whiteList", this.getWhiteList()); + info.put("blackList", this.getBlackList()); return info; } } diff --git a/src/main/java/com/alibaba/druid/wall/spi/MySqlWallVisitor.java b/src/main/java/com/alibaba/druid/wall/spi/MySqlWallVisitor.java index d9905e4c2e..0ab397879f 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/MySqlWallVisitor.java +++ b/src/main/java/com/alibaba/druid/wall/spi/MySqlWallVisitor.java @@ -29,6 +29,7 @@ import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; import com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement; import com.alibaba.druid.sql.ast.statement.SQLAssignItem; +import com.alibaba.druid.sql.ast.statement.SQLCallStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement; @@ -348,4 +349,9 @@ public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisi public boolean visit(MySqlReplaceStatement x) { return true; } + + @Override + public boolean visit(SQLCallStatement x) { + return false; + } } diff --git a/src/main/java/com/alibaba/druid/wall/spi/OracleWallVisitor.java b/src/main/java/com/alibaba/druid/wall/spi/OracleWallVisitor.java index 2aeab53636..18f0f487f0 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/OracleWallVisitor.java +++ b/src/main/java/com/alibaba/druid/wall/spi/OracleWallVisitor.java @@ -27,6 +27,7 @@ import com.alibaba.druid.sql.ast.expr.SQLInListExpr; import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement; +import com.alibaba.druid.sql.ast.statement.SQLCallStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement; @@ -39,6 +40,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; import com.alibaba.druid.sql.ast.statement.SQLSetStatement; import com.alibaba.druid.sql.ast.statement.SQLUnionQuery; import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlReplaceStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateTableStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDeleteStatement; @@ -277,4 +279,13 @@ public class OracleWallVisitor extends OracleASTVisitorAdapter implements WallVi public boolean visit(SQLSetStatement x) { return false; } + + public boolean visit(MySqlReplaceStatement x) { + return true; + } + + @Override + public boolean visit(SQLCallStatement x) { + return false; + } } diff --git a/src/main/java/com/alibaba/druid/wall/spi/PGWallVisitor.java b/src/main/java/com/alibaba/druid/wall/spi/PGWallVisitor.java index 2a94ac9e27..a3160f3479 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/PGWallVisitor.java +++ b/src/main/java/com/alibaba/druid/wall/spi/PGWallVisitor.java @@ -27,6 +27,7 @@ import com.alibaba.druid.sql.ast.expr.SQLInListExpr; import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement; +import com.alibaba.druid.sql.ast.statement.SQLCallStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement; @@ -39,6 +40,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; import com.alibaba.druid.sql.ast.statement.SQLSetStatement; import com.alibaba.druid.sql.ast.statement.SQLUnionQuery; import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlReplaceStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectTableReference; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock; import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitorAdapter; @@ -226,4 +228,13 @@ public class PGWallVisitor extends PGASTVisitorAdapter implements WallVisitor { public boolean visit(SQLSetStatement x) { return false; } + + public boolean visit(MySqlReplaceStatement x) { + return true; + } + + @Override + public boolean visit(SQLCallStatement x) { + return false; + } } diff --git a/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallVisitor.java b/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallVisitor.java index 99e64b4ef5..cf52e9868f 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallVisitor.java +++ b/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallVisitor.java @@ -28,6 +28,7 @@ import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; import com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement; +import com.alibaba.druid.sql.ast.statement.SQLCallStatement; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement; import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement; @@ -40,6 +41,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; import com.alibaba.druid.sql.ast.statement.SQLSetStatement; import com.alibaba.druid.sql.ast.statement.SQLUnionQuery; import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlReplaceStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement; @@ -257,4 +259,13 @@ public class SQLServerWallVisitor extends SQLServerASTVisitorAdapter implements public boolean visit(SQLSetStatement x) { return false; } + + public boolean visit(MySqlReplaceStatement x) { + return true; + } + + @Override + public boolean visit(SQLCallStatement x) { + return false; + } } diff --git a/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java b/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java index 80be0c15e0..d65dae5f06 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java @@ -66,7 +66,9 @@ import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement; import com.alibaba.druid.sql.ast.statement.SQLUnionOperator; import com.alibaba.druid.sql.ast.statement.SQLUnionQuery; import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; +import com.alibaba.druid.sql.ast.statement.SQLUseStatement; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlBooleanExpr; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCommitStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDescribeStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlReplaceStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSetCharSetStatement; @@ -1059,6 +1061,12 @@ public class WallVisitorUtils { } else if (x instanceof MySqlShowStatement) { allow = config.isShowAllow(); denyMessage = "show not allow"; + } else if (x instanceof MySqlCommitStatement) { + allow = config.isCommitAllow(); + denyMessage = "show not allow"; + } else if (x instanceof SQLUseStatement) { + allow = config.isUseAllow(); + denyMessage = "show not allow"; } else { allow = config.isNoneBaseStatementAllow(); } diff --git a/src/main/resources/META-INF/druid/wall/mysql/permit-variant.txt b/src/main/resources/META-INF/druid/wall/mysql/permit-variant.txt index 3c3efbb201..eb91b40358 100644 --- a/src/main/resources/META-INF/druid/wall/mysql/permit-variant.txt +++ b/src/main/resources/META-INF/druid/wall/mysql/permit-variant.txt @@ -18,4 +18,5 @@ sql_big_selects sql_big_tables sql_mode tx_isolation -warning_count \ No newline at end of file +warning_count +@ret \ No newline at end of file diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_blackList_1.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_blackList_1.java index e02658acf9..15c2263fa8 100644 --- a/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_blackList_1.java +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_blackList_1.java @@ -32,7 +32,7 @@ public class WallStatTest_blackList_1 extends TestCase { Assert.assertEquals(0, provider.getBlackListHitCount()); Assert.assertEquals(0, provider.getWhiteListHitCount()); Assert.assertEquals(0, provider.getWhiteList().size()); - Assert.assertEquals(500, provider.getBlackList().size()); + Assert.assertEquals(100, provider.getBlackList().size()); Assert.assertEquals(1001, provider.getCheckCount()); } diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_statMap.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_statMap.java index ee90b52573..f5b4c271e1 100644 --- a/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_statMap.java +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/WallStatTest_statMap.java @@ -1,5 +1,6 @@ package com.alibaba.druid.bvt.filter.wall; +import java.util.Collection; import java.util.Map; import junit.framework.TestCase; @@ -26,26 +27,39 @@ public class WallStatTest_statMap extends TestCase { WallProvider providerA = new MySqlWallProvider(); { - String sql = "select * from t where len(fname) = 1"; - Assert.assertTrue(providerA.checkValid(sql)); + String sql = "select * from t where len(fname) = 1 OR 1 = 1"; + Assert.assertFalse(providerA.checkValid(sql)); } WallProvider providerB = new MySqlWallProvider(); { - String sql = "select * from t where len(fname) = 2"; - Assert.assertTrue(providerB.checkValid(sql)); + String sql = "select * from t where len(fname) = 2 OR 1 = 1"; + Assert.assertFalse(providerB.checkValid(sql)); + } + + WallProvider providerC = new MySqlWallProvider(); + { + String sql = "select * from t where len(fname) = 2 OR 1 = 1"; + Assert.assertFalse(providerC.checkValid(sql)); } Map statMapA = providerA.getStatsMap(); Map statMapB = providerB.getStatsMap(); + Map statMapC = providerC.getStatsMap(); System.out.println(JSONUtils.toJSONString(statMapA)); System.out.println(JSONUtils.toJSONString(statMapB)); + System.out.println(JSONUtils.toJSONString(statMapC)); Map statMapMerged = DruidStatManagerFacade.mergWallStat(statMapA, statMapB); System.out.println(JSONUtils.toJSONString(statMapMerged)); Assert.assertEquals(2L, statMapMerged.get("checkCount")); + Assert.assertEquals(2, ((Collection) statMapMerged.get("blackList")).size()); + + statMapMerged = DruidStatManagerFacade.mergWallStat(statMapMerged, statMapC); + System.out.println(JSONUtils.toJSONString(statMapMerged)); + Assert.assertEquals(2, ((Collection) statMapMerged.get("blackList")).size()); } }