improve sql wall

This commit is contained in:
wenshao
2013-08-26 17:16:04 +08:00
parent 3d8bfacefb
commit e6c893c86f
5 changed files with 156 additions and 10 deletions
@@ -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;
@@ -55,12 +55,14 @@ public abstract class WallProvider {
0.75f,
1);
private boolean whiteListEnable = true;
private LRUCache<String, WallSqlStat> whiteList;
private int MAX_SQL_LENGTH = 2048; // 1k
private int whiteSqlMaxSize = 500; // 1k
private boolean blackListEnable = true;
private LRUCache<String, WallSqlStat> blackList;
private LRUCache<String, WallSqlStat> blackMergedList;
@@ -239,6 +241,12 @@ public abstract class WallProvider {
public WallSqlStat addWhiteSql(String sql, Map<String, WallSqlTableStat> tableStats,
Map<String, WallSqlFunctionStat> 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<String, WallSqlTableStat> tableStats,
Map<String, WallSqlFunctionStat> functionStats, List<Violation> 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<String, Object> 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;
}
}
@@ -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;
@@ -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();
}
}
}
@@ -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));
}
}