improve WallFilter

This commit is contained in:
wenshao
2013-03-17 10:48:21 +08:00
parent e751c2fce1
commit 2548d88fc6
7 changed files with 198 additions and 23 deletions
@@ -19,6 +19,8 @@ import java.security.PrivilegedAction;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import com.alibaba.druid.sql.ast.SQLStatement;
@@ -27,22 +29,26 @@ import com.alibaba.druid.sql.parser.SQLStatementParser;
import com.alibaba.druid.sql.parser.Token;
import com.alibaba.druid.sql.visitor.ExportParameterVisitor;
import com.alibaba.druid.util.LRUCache;
import com.alibaba.druid.wall.spi.WallVisitorUtils;
import com.alibaba.druid.wall.violation.IllegalSQLObjectViolation;
import com.alibaba.druid.wall.violation.SyntaxErrorViolation;
public abstract class WallProvider {
private LinkedHashMap<String, WallSqlStat> whiteList;
private LinkedHashMap<String, WallSqlStat> whiteList;
private int whileListMaxSize = 1024;
private int whileListMaxSize = 1024;
private int whiteSqlMaxLength = 1024; // 1k
private int whiteSqlMaxLength = 1024; // 1k
protected final WallConfig config;
protected final WallConfig config;
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private static final ThreadLocal<Boolean> privileged = new ThreadLocal<Boolean>();
private static final ThreadLocal<Boolean> privileged = new ThreadLocal<Boolean>();
private final ConcurrentMap<String, WallDenyStat> deniedTables = new ConcurrentHashMap<String, WallDenyStat>();
private final ConcurrentMap<String, WallDenyStat> deniedFunctions = new ConcurrentHashMap<String, WallDenyStat>();
public WallProvider(WallConfig config){
this.config = config;
@@ -78,7 +84,7 @@ public abstract class WallProvider {
return hashSet;
}
public void clearCache() {
clearWhiteList();
}
@@ -93,15 +99,15 @@ public abstract class WallProvider {
lock.writeLock().unlock();
}
}
public WallSqlStat getWhiteSql(String sql) {
lock.readLock().lock();
try {
if (whiteList == null) {
return null;
}
return whiteList.get(sql);
return whiteList.get(sql);
} finally {
lock.readLock().unlock();
}
@@ -122,6 +128,72 @@ public abstract class WallProvider {
return result.getViolations().isEmpty();
}
public boolean checkDenyFunction(String functionName) {
if (functionName == null) {
return true;
}
functionName = functionName.toLowerCase();
if (getConfig().getDenyFunctions().contains(functionName)) {
WallDenyStat denyStat = this.deniedFunctions.get(functionName);
if (denyStat == null) {
this.deniedFunctions.putIfAbsent(functionName, new WallDenyStat());
denyStat = this.deniedFunctions.get(functionName);
}
denyStat.incrementAndGetDenyCount();
return false;
}
return true;
}
public boolean checkDenyTable(String tableName) {
if (tableName == null) {
return true;
}
tableName = WallVisitorUtils.form(tableName);
if (getConfig().getDenyTables().contains(tableName)) {
WallDenyStat denyStat = this.deniedTables.get(tableName);
if (denyStat == null) {
this.deniedTables.putIfAbsent(tableName, new WallDenyStat());
denyStat = this.deniedTables.get(tableName);
}
denyStat.incrementAndGetDenyCount();
return false;
}
return true;
}
public boolean checkReadOnlyTable(String tableName) {
if (tableName == null) {
return true;
}
tableName = WallVisitorUtils.form(tableName);
if (getConfig().isReadOnly(tableName)) {
WallDenyStat denyStat = this.deniedTables.get(tableName);
if (denyStat == null) {
this.deniedTables.putIfAbsent(tableName, new WallDenyStat());
denyStat = this.deniedTables.get(tableName);
}
denyStat.incrementAndGetDenyCount();
return false;
}
return true;
}
public WallDenyStat getDenniedTableStat(String tableName) {
if (tableName == null) {
return null;
}
String formName = WallVisitorUtils.form(tableName);
return deniedTables.get(formName);
}
public WallCheckResult check(String sql) {
WallCheckResult result = new WallCheckResult();
@@ -242,8 +242,7 @@ public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisi
return false;
}
name = WallVisitorUtils.form(name);
return config.getDenyTables().contains(name);
return !this.provider.checkDenyTable(name);
}
public void preVisit(SQLObject x) {
@@ -167,7 +167,7 @@ public class OracleWallVisitor extends OracleASTVisitorAdapter implements WallVi
if (name.startsWith("v$") || name.startsWith("v_$")) {
return true;
}
return config.getDenyTables().contains(name);
return !this.provider.checkDenyTable(name);
}
public void preVisit(SQLObject x) {
@@ -85,8 +85,7 @@ public class SQLServerWallVisitor extends SQLServerASTVisitorAdapter implements
return false;
}
name = WallVisitorUtils.form(name);
return config.getDenyTables().contains(name);
return !this.provider.checkDenyTable(name);
}
@Override
@@ -69,7 +69,7 @@ import com.alibaba.druid.wall.violation.IllegalSQLObjectViolation;
public class WallVisitorUtils {
private final static Log LOG = LogFactory.getLog(WallVisitorUtils.class);
private final static Log LOG = LogFactory.getLog(WallVisitorUtils.class);
public static void check(WallVisitor visitor, SQLInListExpr x) {
@@ -88,7 +88,7 @@ public class WallVisitorUtils {
&& x.getParent() instanceof SQLSelectQueryBlock) {
SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) x.getParent();
SQLTableSource from = queryBlock.getFrom();
if (from instanceof SQLExprTableSource) {
addViolation(visitor, x);
}
@@ -348,11 +348,9 @@ public class WallVisitorUtils {
tableName = ((SQLName) tableNameExpr).getSimleName();
}
if (tableName != null) {
tableName = form(tableName);
if (visitor.getConfig().isReadOnly(tableName)) {
addViolation(visitor, tableSource);
}
boolean readOnlyValid = visitor.getProvider().checkReadOnlyTable(tableName);
if (!readOnlyValid) {
addViolation(visitor, tableSource);
}
} else if (tableSource instanceof SQLJoinTableSource) {
SQLJoinTableSource join = (SQLJoinTableSource) tableSource;
@@ -737,7 +735,7 @@ public class WallVisitorUtils {
String methodName = x.getMethodName();
if (visitor.getConfig().isDenyFunction(methodName.toLowerCase())) {
if (!visitor.getProvider().checkDenyFunction(methodName)) {
addViolation(visitor, x);
}