mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
improve WallFilter
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user