diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java index 46345b562d..dba48c20bd 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLEvalVisitorUtils.java @@ -91,7 +91,6 @@ import com.alibaba.druid.sql.visitor.functions.Ucase; import com.alibaba.druid.sql.visitor.functions.Unhex; import com.alibaba.druid.util.HexBin; import com.alibaba.druid.util.JdbcUtils; -import com.alibaba.druid.wall.WallContext; import com.alibaba.druid.wall.spi.WallVisitorUtils; import com.alibaba.druid.wall.spi.WallVisitorUtils.WallConditionContext; import com.alibaba.druid.wall.spi.WallVisitorUtils.WallSelectQueryContext; diff --git a/src/main/java/com/alibaba/druid/wall/WallProvider.java b/src/main/java/com/alibaba/druid/wall/WallProvider.java index 14708f8e4f..394b507345 100644 --- a/src/main/java/com/alibaba/druid/wall/WallProvider.java +++ b/src/main/java/com/alibaba/druid/wall/WallProvider.java @@ -55,12 +55,14 @@ public abstract class WallProvider { 0.75f, 1); + private boolean whiteListEnable = true; private LRUCache whiteList; private int MAX_SQL_LENGTH = 2048; // 1k private int whiteSqlMaxSize = 500; // 1k + private boolean blackListEnable = true; private LRUCache blackList; private LRUCache blackMergedList; @@ -239,6 +241,12 @@ public abstract class WallProvider { public WallSqlStat addWhiteSql(String sql, Map tableStats, Map functionStats, boolean syntaxError) { + + if (!whiteListEnable) { + WallSqlStat stat = new WallSqlStat(tableStats, functionStats, syntaxError); + return stat; + } + String mergedSql; try { mergedSql = ParameterizedOutputVisitorUtils.parameterize(sql, dbType); @@ -306,6 +314,11 @@ public abstract class WallProvider { public WallSqlStat addBlackSql(String sql, Map tableStats, Map functionStats, List violations, boolean syntaxError) { + if (!blackListEnable) { + WallSqlStat stat = new WallSqlStat(tableStats, functionStats, syntaxError); + return stat; + } + String mergedSql; try { mergedSql = ParameterizedOutputVisitorUtils.parameterize(sql, dbType); @@ -364,7 +377,7 @@ public abstract class WallProvider { if (whiteList != null) { hashSet.addAll(whiteList.keySet()); } - + if (blackMergedList != null) { hashSet.addAll(blackMergedList.keySet()); } @@ -705,7 +718,7 @@ public abstract class WallProvider { } private WallCheckResult checkWhiteAndBlackList(String sql) { - { + if (whiteListEnable) { WallSqlStat sqlStat = getWhiteSql(sql); if (sqlStat != null) { whiteListHitCount.incrementAndGet(); @@ -724,7 +737,7 @@ public abstract class WallProvider { } } // check black list - { + if (blackListEnable) { WallSqlStat sqlStat = getBlackSql(sql); if (sqlStat != null) { blackListHitCount.incrementAndGet(); @@ -919,14 +932,14 @@ public abstract class WallProvider { } sqlStatValue.setSql(sql); - + long sqlHash = sqlStat.getSqlHash(); if (sqlHash == 0) { sqlHash = Utils.murmurhash2_64(sql); sqlStat.setSqlHash(sqlHash); } sqlStatValue.setSqlHash(sqlHash); - + statValue.getWhiteList().add(sqlStatValue); } } @@ -955,4 +968,20 @@ public abstract class WallProvider { public Map getStatsMap() { return getStatValue(false).toMap(); } + + public boolean isWhiteListEnable() { + return whiteListEnable; + } + + public void setWhiteListEnable(boolean whiteListEnable) { + this.whiteListEnable = whiteListEnable; + } + + public boolean isBlackListEnable() { + return blackListEnable; + } + + public void setBlackListEnable(boolean blackListEnable) { + this.blackListEnable = blackListEnable; + } } 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 3a6ca2b3e3..26aba10a06 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java @@ -1011,15 +1011,16 @@ public class WallVisitorUtils { } } + String dbType = null; + if (visitor != null) { + dbType = visitor.getDbType(); + } + if (x instanceof SQLMethodInvokeExpr // || x instanceof SQLBetweenExpr // || x instanceof SQLInListExpr // || x instanceof SQLUnaryExpr // ) { - String dbType = null; - if (visitor != null) { - dbType = visitor.getDbType(); - } return SQLEvalVisitorUtils.eval(dbType, x, Collections.emptyList(), false); } @@ -1032,6 +1033,8 @@ public class WallVisitorUtils { addViolation(visitor, ErrorCode.CONST_CASE_CONDITION, "const case condition", caseExpr); } } + + return SQLEvalVisitorUtils.eval(dbType, x, Collections.emptyList(), false); } return null; diff --git a/src/test/java/com/alibaba/druid/benckmark/wall/WallBenchmarkTest_mysql_concurrent.java b/src/test/java/com/alibaba/druid/benckmark/wall/WallBenchmarkTest_mysql_concurrent.java new file mode 100644 index 0000000000..06141d7203 --- /dev/null +++ b/src/test/java/com/alibaba/druid/benckmark/wall/WallBenchmarkTest_mysql_concurrent.java @@ -0,0 +1,79 @@ +/* + * Copyright 1999-2011 Alibaba Group Holding Ltd. + * + * 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.alibaba.druid.benckmark.wall; + +import java.util.concurrent.CountDownLatch; + +import junit.framework.TestCase; + +import com.alibaba.druid.wall.WallProvider; +import com.alibaba.druid.wall.spi.MySqlWallProvider; + +public class WallBenchmarkTest_mysql_concurrent extends TestCase { + + WallProvider provider = new MySqlWallProvider(); + + public final static int COUNT = 1000 * 10; + + public void test_0() throws Exception { + String sql = "SELECT t1.department_id, t2.*\n" + // + "FROM hr_info t1, x2 t2\n" + // + "WHERE t2.department_id = t1.department_id"; + for (int i = 0; i < 10; ++i) { + provider.clearCache(); + long startMillis = System.currentTimeMillis(); + perf(sql, 10); + long millis = System.currentTimeMillis() - startMillis; + System.out.println("millis : " + millis); + } + } + + public void perf(final String sql, int threadCount) { + final CountDownLatch startLatch = new CountDownLatch(1); + final CountDownLatch latch = new CountDownLatch(threadCount); + for (int i = 0; i < threadCount; ++i) { + final int seed = i * 1000 * 1000 * 100; + Thread thread = new Thread() { + + public void run() { + try { + startLatch.await(); + for (int i = 0; i < COUNT; ++i) { + int id = seed + i; + String text = sql + " AND FID = " + id; + provider.check(text); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + latch.countDown(); + } + } + }; + thread.setName("perf-" + i); + thread.start(); + } + + startLatch.countDown(); + + try { + latch.await(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest128.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest128.java new file mode 100644 index 0000000000..9856b30f9f --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/MySqlWallTest128.java @@ -0,0 +1,36 @@ +/* + * Copyright 1999-2011 Alibaba Group Holding Ltd. + * + * 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.alibaba.druid.bvt.filter.wall; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.wall.WallProvider; +import com.alibaba.druid.wall.spi.MySqlWallProvider; + +public class MySqlWallTest128 extends TestCase { + + public void test_false() throws Exception { + WallProvider provider = new MySqlWallProvider(); + provider.getConfig().setCommentAllow(false); + + String sql = "SELECT name, '******' password, createTime from user where name like 'admin' AND (CASE WHEN (7885=7885) THEN 1 ELSE 0 END)"; + + Assert.assertFalse(provider.checkValid(sql)); + } + +}