mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
improve wall filter
This commit is contained in:
@@ -28,7 +28,9 @@ public class SQLPropertyExpr extends SQLExprImpl implements SQLName {
|
||||
private String name;
|
||||
|
||||
public SQLPropertyExpr(SQLExpr owner, String name){
|
||||
|
||||
if (owner != null) {
|
||||
owner.setParent(this);
|
||||
}
|
||||
this.owner = owner;
|
||||
this.name = name;
|
||||
}
|
||||
@@ -46,6 +48,9 @@ public class SQLPropertyExpr extends SQLExprImpl implements SQLName {
|
||||
}
|
||||
|
||||
public void setOwner(SQLExpr owner) {
|
||||
if (owner != null) {
|
||||
owner.setParent(this);
|
||||
}
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ import java.util.List;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLName;
|
||||
import com.alibaba.druid.sql.ast.SQLStatementImpl;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
|
||||
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
|
||||
public class SQLAlterTableStatement extends SQLStatementImpl implements SQLDDLStatement {
|
||||
|
||||
@@ -54,4 +56,13 @@ public class SQLAlterTableStatement extends SQLStatementImpl implements SQLDDLSt
|
||||
public void setName(SQLName name) {
|
||||
this.setTableSource(new SQLExprTableSource(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void accept0(SQLASTVisitor visitor) {
|
||||
if (visitor.visit(this)) {
|
||||
acceptChild(visitor, getTableSource());
|
||||
acceptChild(visitor, getItems());
|
||||
}
|
||||
visitor.endVisit(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,9 @@ public class SQLDeleteStatement extends SQLStatementImpl {
|
||||
}
|
||||
|
||||
public void setTableSource(SQLTableSource tableSource) {
|
||||
if (tableSource != null) {
|
||||
tableSource.setParent(this);
|
||||
}
|
||||
this.tableSource = tableSource;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,9 @@ public abstract class SQLInsertInto extends SQLObjectImpl {
|
||||
}
|
||||
|
||||
public void setTableSource(SQLExprTableSource tableSource) {
|
||||
if (tableSource != null) {
|
||||
tableSource.setParent(this);
|
||||
}
|
||||
this.tableSource = tableSource;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,9 @@ public class SQLJoinTableSource extends SQLTableSourceImpl {
|
||||
}
|
||||
|
||||
public void setLeft(SQLTableSource left) {
|
||||
if (left != null) {
|
||||
left.setParent(this);
|
||||
}
|
||||
this.left = left;
|
||||
}
|
||||
|
||||
@@ -71,6 +74,9 @@ public class SQLJoinTableSource extends SQLTableSourceImpl {
|
||||
}
|
||||
|
||||
public void setRight(SQLTableSource right) {
|
||||
if (right != null) {
|
||||
right.setParent(this);
|
||||
}
|
||||
this.right = right;
|
||||
}
|
||||
|
||||
@@ -79,6 +85,9 @@ public class SQLJoinTableSource extends SQLTableSourceImpl {
|
||||
}
|
||||
|
||||
public void setCondition(SQLExpr condition) {
|
||||
if (condition != null) {
|
||||
condition.setParent(this);
|
||||
}
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,10 +43,13 @@ public class SQLSelectQueryBlock extends SQLSelectQuery {
|
||||
}
|
||||
|
||||
public void setInto(SQLExpr into) {
|
||||
this.into = new SQLExprTableSource(into);
|
||||
this.setInto(new SQLExprTableSource(into));
|
||||
}
|
||||
|
||||
public void setInto(SQLExprTableSource into) {
|
||||
if (into != null) {
|
||||
into.setParent(this);
|
||||
}
|
||||
this.into = into;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,9 @@ public class SQLTruncateStatement extends SQLStatementImpl {
|
||||
}
|
||||
|
||||
public void addTableSource(SQLName name) {
|
||||
this.tableSources.add(new SQLExprTableSource(name));
|
||||
SQLExprTableSource tableSource = new SQLExprTableSource(name);
|
||||
tableSource.setParent(this);
|
||||
this.tableSources.add(tableSource);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -45,6 +45,9 @@ public class SQLUpdateStatement extends SQLStatementImpl {
|
||||
}
|
||||
|
||||
public void setTableSource(SQLTableSource tableSource) {
|
||||
if (tableSource != null) {
|
||||
tableSource.setParent(this);
|
||||
}
|
||||
this.tableSource = tableSource;
|
||||
}
|
||||
|
||||
|
||||
@@ -203,12 +203,12 @@ public class MySqlLexer extends Lexer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected final void scanString() {
|
||||
{
|
||||
boolean hasSpecial = false;
|
||||
int startIndex = pos + 1;
|
||||
int endIndex = -1; //text.indexOf('\'', startIndex);
|
||||
int endIndex = -1; // text.indexOf('\'', startIndex);
|
||||
for (int i = startIndex; i < text.length(); ++i) {
|
||||
final char ch = text.charAt(i);
|
||||
if (ch == '\\') {
|
||||
@@ -219,13 +219,13 @@ public class MySqlLexer extends Lexer {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (endIndex == -1) {
|
||||
throw new ParserException("unclosed str");
|
||||
}
|
||||
|
||||
String stringVal = subString(startIndex, endIndex - startIndex);
|
||||
// hasSpecial = stringVal.indexOf('\\') != -1;
|
||||
// hasSpecial = stringVal.indexOf('\\') != -1;
|
||||
|
||||
if (!hasSpecial) {
|
||||
this.stringVal = stringVal;
|
||||
@@ -328,6 +328,8 @@ public class MySqlLexer extends Lexer {
|
||||
}
|
||||
|
||||
public void scanComment() {
|
||||
Token lastToken = this.token;
|
||||
|
||||
if (ch != '/' && ch != '-') {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
@@ -374,8 +376,14 @@ public class MySqlLexer extends Lexer {
|
||||
token = Token.MULTI_LINE_COMMENT;
|
||||
}
|
||||
|
||||
if (token != Token.HINT && !isAllowComment()) {
|
||||
throw new NotAllowCommentException();
|
||||
if (token != Token.HINT) {
|
||||
if (commentHandler != null && commentHandler.handle(lastToken, stringVal)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isAllowComment()) {
|
||||
throw new NotAllowCommentException();
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
@@ -64,10 +64,15 @@ public class MySqlSelectParser extends SQLSelectParser {
|
||||
|
||||
if (lexer.token() == Token.SELECT) {
|
||||
lexer.nextToken();
|
||||
|
||||
|
||||
if (lexer.token() == Token.HINT) {
|
||||
this.exprParser.parseHints(queryBlock.getHints());
|
||||
}
|
||||
|
||||
if (lexer.token() == Token.COMMENT) {
|
||||
lexer.nextToken();
|
||||
}
|
||||
|
||||
if (lexer.token() == (Token.DISTINCT)) {
|
||||
queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);
|
||||
|
||||
@@ -235,6 +235,10 @@ public class MySqlStatementParser extends SQLStatementParser {
|
||||
|
||||
if (lexer.token() == Token.DELETE) {
|
||||
lexer.nextToken();
|
||||
|
||||
if (lexer.token() == Token.COMMENT) {
|
||||
lexer.nextToken();
|
||||
}
|
||||
|
||||
if (identifierEquals(LOW_PRIORITY)) {
|
||||
deleteStatement.setLowPriority(true);
|
||||
|
||||
@@ -244,6 +244,10 @@ public class OracleSelectParser extends SQLSelectParser {
|
||||
OracleSelectQueryBlock queryBlock = new OracleSelectQueryBlock();
|
||||
if (lexer.token() == Token.SELECT) {
|
||||
lexer.nextToken();
|
||||
|
||||
if (lexer.token() == Token.COMMENT) {
|
||||
lexer.nextToken();
|
||||
}
|
||||
|
||||
parseHints(queryBlock);
|
||||
|
||||
|
||||
@@ -1462,6 +1462,10 @@ public class OracleStatementParser extends SQLStatementParser {
|
||||
|
||||
if (lexer.token() == Token.DELETE) {
|
||||
lexer.nextToken();
|
||||
|
||||
if (lexer.token() == Token.COMMENT) {
|
||||
lexer.nextToken();
|
||||
}
|
||||
|
||||
parseHints(deleteStatement.getHints());
|
||||
|
||||
|
||||
@@ -66,6 +66,11 @@ public class PGInsertStatement extends SQLInsertStatement implements PGSQLStatem
|
||||
public List<ValuesClause> getValuesList() {
|
||||
return valuesList;
|
||||
}
|
||||
|
||||
public void addValueCause(ValuesClause valueClause) {
|
||||
valueClause.setParent(this);
|
||||
valuesList.add(valueClause);
|
||||
}
|
||||
|
||||
protected void accept0(SQLASTVisitor visitor) {
|
||||
accept0((PGASTVisitor) visitor);
|
||||
|
||||
+4
-3
@@ -110,9 +110,10 @@ public class PGSQLStatementParser extends SQLStatementParser {
|
||||
|
||||
for (;;) {
|
||||
accept(Token.LPAREN);
|
||||
SQLInsertStatement.ValuesClause values = new SQLInsertStatement.ValuesClause();
|
||||
this.exprParser.exprList(values.getValues());
|
||||
stmt.getValuesList().add(values);
|
||||
SQLInsertStatement.ValuesClause valuesCaluse = new SQLInsertStatement.ValuesClause();
|
||||
this.exprParser.exprList(valuesCaluse.getValues());
|
||||
stmt.addValueCause(valuesCaluse);
|
||||
|
||||
accept(Token.RPAREN);
|
||||
if (lexer.token() == Token.COMMA) {
|
||||
lexer.nextToken();
|
||||
|
||||
@@ -52,6 +52,10 @@ public class PGSelectParser extends SQLSelectParser {
|
||||
|
||||
if (lexer.token() == Token.SELECT) {
|
||||
lexer.nextToken();
|
||||
|
||||
if (lexer.token() == Token.COMMENT) {
|
||||
lexer.nextToken();
|
||||
}
|
||||
|
||||
if (lexer.token() == Token.DISTINCT) {
|
||||
queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);
|
||||
|
||||
+4
@@ -66,6 +66,10 @@ public class SQLServerSelectParser extends SQLSelectParser {
|
||||
|
||||
if (lexer.token() == Token.SELECT) {
|
||||
lexer.nextToken();
|
||||
|
||||
if (lexer.token() == Token.COMMENT) {
|
||||
lexer.nextToken();
|
||||
}
|
||||
|
||||
if (lexer.token() == Token.DISTINCT) {
|
||||
queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);
|
||||
|
||||
@@ -68,10 +68,20 @@ public class Lexer {
|
||||
|
||||
private int varIndex = -1;
|
||||
|
||||
protected CommentHandler commentHandler;
|
||||
|
||||
public Lexer(String input){
|
||||
this(input, true);
|
||||
}
|
||||
|
||||
public CommentHandler getCommentHandler() {
|
||||
return commentHandler;
|
||||
}
|
||||
|
||||
public void setCommentHandler(CommentHandler commentHandler) {
|
||||
this.commentHandler = commentHandler;
|
||||
}
|
||||
|
||||
public final char charAt(int index) {
|
||||
if (index >= text.length()) {
|
||||
return EOI;
|
||||
@@ -1008,4 +1018,9 @@ public class Lexer {
|
||||
public BigDecimal decimalValue() {
|
||||
return new BigDecimal(text.toCharArray(), mark, bufPos);
|
||||
}
|
||||
|
||||
public static interface CommentHandler {
|
||||
|
||||
boolean handle(Token lastToken, String comment);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ public class NotAllowCommentException extends ParserException {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public NotAllowCommentException(){
|
||||
super();
|
||||
this("comment not allow");
|
||||
}
|
||||
|
||||
public NotAllowCommentException(String message, Throwable e){
|
||||
|
||||
@@ -141,6 +141,10 @@ public class SQLSelectParser extends SQLParser {
|
||||
}
|
||||
|
||||
accept(Token.SELECT);
|
||||
|
||||
if (lexer.token() == Token.COMMENT) {
|
||||
lexer.nextToken();
|
||||
}
|
||||
|
||||
SQLSelectQueryBlock queryBlock = new SQLSelectQueryBlock();
|
||||
|
||||
|
||||
@@ -617,6 +617,10 @@ public class SQLStatementParser extends SQLParser {
|
||||
if (lexer.token() == (Token.FROM)) {
|
||||
lexer.nextToken();
|
||||
}
|
||||
|
||||
if (lexer.token() == Token.COMMENT) {
|
||||
lexer.nextToken();
|
||||
}
|
||||
|
||||
SQLName tableName = exprParser.name();
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ import com.alibaba.druid.sql.ast.statement.SQLAlterTableDropForeinKey;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableDropIndex;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableDropPrimaryKey;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableEnableKeys;
|
||||
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.SQLCharactorDataType;
|
||||
@@ -449,4 +450,8 @@ public interface SQLASTVisitor {
|
||||
boolean visit(SQLAlterTableEnableKeys x);
|
||||
|
||||
void endVisit(SQLAlterTableEnableKeys x);
|
||||
|
||||
boolean visit(SQLAlterTableStatement x);
|
||||
|
||||
void endVisit(SQLAlterTableStatement x);
|
||||
}
|
||||
|
||||
@@ -62,6 +62,7 @@ import com.alibaba.druid.sql.ast.statement.SQLAlterTableDropForeinKey;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableDropIndex;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableDropPrimaryKey;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableEnableKeys;
|
||||
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.SQLCharactorDataType;
|
||||
@@ -831,4 +832,14 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor {
|
||||
public void endVisit(SQLAlterTableEnableKeys x) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLAlterTableStatement x) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(SQLAlterTableStatement x) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,9 @@ public class WallConfig implements WallConfigMBean {
|
||||
private boolean selectWhereAlwayTrueCheck = true;
|
||||
private boolean selectHavingAlwayTrueCheck = true;
|
||||
private boolean selectUnionCheck = true;
|
||||
private boolean createTableAllow = false;
|
||||
private boolean dropTableAllow = false;
|
||||
private boolean alterTableAllow = false;
|
||||
|
||||
private boolean selectAllColumnAllow = true;
|
||||
|
||||
@@ -285,6 +288,30 @@ public class WallConfig implements WallConfigMBean {
|
||||
this.selectIntoOutfileAllow = selectIntoOutfileAllow;
|
||||
}
|
||||
|
||||
public boolean isCreateTableAllow() {
|
||||
return createTableAllow;
|
||||
}
|
||||
|
||||
public void setCreateTableAllow(boolean createTableAllow) {
|
||||
this.createTableAllow = createTableAllow;
|
||||
}
|
||||
|
||||
public boolean isDropTableAllow() {
|
||||
return dropTableAllow;
|
||||
}
|
||||
|
||||
public void setDropTableAllow(boolean dropTableAllow) {
|
||||
this.dropTableAllow = dropTableAllow;
|
||||
}
|
||||
|
||||
public boolean isAlterTableAllow() {
|
||||
return alterTableAllow;
|
||||
}
|
||||
|
||||
public void setAlterTableAllow(boolean alterTableAllow) {
|
||||
this.alterTableAllow = alterTableAllow;
|
||||
}
|
||||
|
||||
public boolean isSelectUnionCheck() {
|
||||
return selectUnionCheck;
|
||||
}
|
||||
|
||||
@@ -15,17 +15,40 @@
|
||||
*/
|
||||
package com.alibaba.druid.wall;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class WallContext {
|
||||
|
||||
private final static ThreadLocal<WallContext> contextLocal = new ThreadLocal<WallContext>();
|
||||
|
||||
private WallSqlStat sqlState;
|
||||
private Map<String, WallSqlTableStat> tableStats;
|
||||
private final String dbType;
|
||||
|
||||
public WallContext(String dbType){
|
||||
this.dbType = dbType;
|
||||
}
|
||||
|
||||
public WallSqlTableStat getTableStat(String tableName) {
|
||||
if (tableStats == null) {
|
||||
tableStats = new HashMap<String, WallSqlTableStat>(2);
|
||||
}
|
||||
|
||||
String lowerCaseName = tableName.toLowerCase();
|
||||
|
||||
WallSqlTableStat stat = tableStats.get(lowerCaseName);
|
||||
if (stat == null) {
|
||||
if (tableStats.size() > 10000) {
|
||||
return null;
|
||||
}
|
||||
|
||||
stat = new WallSqlTableStat();
|
||||
tableStats.put(tableName, stat);
|
||||
}
|
||||
return stat;
|
||||
}
|
||||
|
||||
public static WallContext createIfNotExists(String dbType) {
|
||||
WallContext context = contextLocal.get();
|
||||
if (context == null) {
|
||||
@@ -35,6 +58,12 @@ public class WallContext {
|
||||
return context;
|
||||
}
|
||||
|
||||
public static WallContext create(String dbType) {
|
||||
WallContext context = new WallContext(dbType);
|
||||
contextLocal.set(context);
|
||||
return context;
|
||||
}
|
||||
|
||||
public static WallContext current() {
|
||||
return contextLocal.get();
|
||||
}
|
||||
@@ -51,6 +80,10 @@ public class WallContext {
|
||||
this.sqlState = sqlState;
|
||||
}
|
||||
|
||||
public Map<String, WallSqlTableStat> getTableStats() {
|
||||
return tableStats;
|
||||
}
|
||||
|
||||
public String getDbType() {
|
||||
return dbType;
|
||||
}
|
||||
|
||||
@@ -16,14 +16,18 @@
|
||||
package com.alibaba.druid.wall;
|
||||
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.parser.Lexer;
|
||||
import com.alibaba.druid.sql.parser.NotAllowCommentException;
|
||||
import com.alibaba.druid.sql.parser.ParserException;
|
||||
import com.alibaba.druid.sql.parser.SQLStatementParser;
|
||||
@@ -36,25 +40,36 @@ import com.alibaba.druid.wall.violation.SyntaxErrorViolation;
|
||||
|
||||
public abstract class WallProvider {
|
||||
|
||||
private LinkedHashMap<String, WallSqlStat> whiteList;
|
||||
private LRUCache<String, WallSqlStat> whiteList;
|
||||
|
||||
private int whileListMaxSize = 1024;
|
||||
private int MAX_SQL_SIZE = 2048; // 1k
|
||||
|
||||
private int whiteSqlMaxLength = 1024; // 1k
|
||||
private int whiteSqlMaxLength = 1024; // 1k
|
||||
|
||||
protected final WallConfig config;
|
||||
private LRUCache<String, WallSqlStat> blackList;
|
||||
|
||||
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
private int blackSqlMaxLength = 1024; // 1k
|
||||
|
||||
private static final ThreadLocal<Boolean> privileged = new ThreadLocal<Boolean>();
|
||||
protected final WallConfig config;
|
||||
|
||||
private final ConcurrentMap<String, WallDenyStat> deniedTables = new ConcurrentHashMap<String, WallDenyStat>();
|
||||
private final ConcurrentMap<String, WallDenyStat> deniedFunctions = new ConcurrentHashMap<String, WallDenyStat>();
|
||||
private final ConcurrentMap<String, WallDenyStat> deniedSchemas = new ConcurrentHashMap<String, WallDenyStat>();
|
||||
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||
|
||||
public final WallDenyStat commentDeniedStat = new WallDenyStat();
|
||||
private static final ThreadLocal<Boolean> privileged = new ThreadLocal<Boolean>();
|
||||
|
||||
protected String dbType = null;
|
||||
private final ConcurrentMap<String, WallDenyStat> deniedTables = new ConcurrentHashMap<String, WallDenyStat>();
|
||||
private final ConcurrentMap<String, WallDenyStat> deniedFunctions = new ConcurrentHashMap<String, WallDenyStat>();
|
||||
private final ConcurrentMap<String, WallDenyStat> deniedSchemas = new ConcurrentHashMap<String, WallDenyStat>();
|
||||
|
||||
private final ConcurrentMap<String, WallTableStat> tableStats = new ConcurrentHashMap<String, WallTableStat>();
|
||||
|
||||
public final WallDenyStat commentDeniedStat = new WallDenyStat();
|
||||
|
||||
protected String dbType = null;
|
||||
protected AtomicLong checkCount = new AtomicLong();
|
||||
protected AtomicLong whiteListHitCount = new AtomicLong();
|
||||
protected AtomicLong blackListHitCount = new AtomicLong();
|
||||
protected AtomicLong syntaxErrrorCount = new AtomicLong();
|
||||
protected AtomicLong violationCount = new AtomicLong();
|
||||
|
||||
public WallProvider(WallConfig config){
|
||||
this.config = config;
|
||||
@@ -65,18 +80,70 @@ public abstract class WallProvider {
|
||||
this.dbType = dbType;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
this.clearWhiteList();
|
||||
this.deniedTables.clear();
|
||||
this.deniedFunctions.clear();
|
||||
this.deniedSchemas.clear();
|
||||
this.tableStats.clear();
|
||||
}
|
||||
|
||||
public ConcurrentMap<String, WallTableStat> getTableStats() {
|
||||
return this.tableStats;
|
||||
}
|
||||
|
||||
public WallTableStat getTableStat(String tableName) {
|
||||
String lowerCaseName = tableName.toLowerCase();
|
||||
|
||||
WallTableStat stat = tableStats.get(lowerCaseName);
|
||||
if (stat == null) {
|
||||
if (tableStats.size() > 10000) {
|
||||
return null;
|
||||
}
|
||||
|
||||
tableStats.putIfAbsent(lowerCaseName, new WallTableStat());
|
||||
stat = tableStats.get(lowerCaseName);
|
||||
}
|
||||
return stat;
|
||||
}
|
||||
|
||||
public WallConfig getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public void addWhiteSql(String sql) {
|
||||
public WallSqlStat addWhiteSql(String sql, Map<String, WallSqlTableStat> tableStats) {
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
if (whiteList == null) {
|
||||
whiteList = new LRUCache<String, WallSqlStat>(whileListMaxSize);
|
||||
whiteList = new LRUCache<String, WallSqlStat>(whiteSqlMaxLength);
|
||||
}
|
||||
|
||||
whiteList.put(sql, new WallSqlStat());
|
||||
WallSqlStat wallStat = whiteList.get(sql);
|
||||
if (wallStat == null) {
|
||||
wallStat = new WallSqlStat(tableStats);
|
||||
whiteList.put(sql, wallStat);
|
||||
}
|
||||
|
||||
return wallStat;
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public WallSqlStat addBlackSql(String sql, Map<String, WallSqlTableStat> tableStats, List<Violation> violations) {
|
||||
lock.writeLock().lock();
|
||||
try {
|
||||
if (blackList == null) {
|
||||
blackList = new LRUCache<String, WallSqlStat>(blackSqlMaxLength);
|
||||
}
|
||||
|
||||
WallSqlStat wallStat = blackList.get(sql);
|
||||
if (wallStat == null) {
|
||||
wallStat = new WallSqlStat(tableStats, violations);
|
||||
blackList.put(sql, wallStat);
|
||||
}
|
||||
|
||||
return wallStat;
|
||||
} finally {
|
||||
lock.writeLock().unlock();
|
||||
}
|
||||
@@ -93,7 +160,21 @@ public abstract class WallProvider {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
|
||||
return hashSet;
|
||||
return Collections.<String> unmodifiableSet(hashSet);
|
||||
}
|
||||
|
||||
public Set<String> getBlackList() {
|
||||
Set<String> hashSet = new HashSet<String>();
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
if (blackList != null) {
|
||||
hashSet.addAll(blackList.keySet());
|
||||
}
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
|
||||
return Collections.<String> unmodifiableSet(hashSet);
|
||||
}
|
||||
|
||||
public void clearCache() {
|
||||
@@ -124,6 +205,19 @@ public abstract class WallProvider {
|
||||
}
|
||||
}
|
||||
|
||||
public WallSqlStat getBlackSql(String sql) {
|
||||
lock.readLock().lock();
|
||||
try {
|
||||
if (blackList == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return blackList.get(sql);
|
||||
} finally {
|
||||
lock.readLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean whiteContains(String sql) {
|
||||
return getWhiteSql(sql) != null;
|
||||
}
|
||||
@@ -138,10 +232,11 @@ public abstract class WallProvider {
|
||||
WallContext originalContext = WallContext.current();
|
||||
|
||||
try {
|
||||
WallContext.createIfNotExists(dbType);
|
||||
WallCheckResult result = check(sql);
|
||||
WallContext.create(dbType);
|
||||
WallCheckResult result = checkInternal(sql);
|
||||
return result.getViolations().isEmpty();
|
||||
} finally {
|
||||
|
||||
if (originalContext == null) {
|
||||
WallContext.clearContext();
|
||||
}
|
||||
@@ -251,6 +346,21 @@ public abstract class WallProvider {
|
||||
}
|
||||
|
||||
public WallCheckResult check(String sql) {
|
||||
WallContext originalContext = WallContext.current();
|
||||
|
||||
try {
|
||||
WallContext.create(dbType);
|
||||
return checkInternal(sql);
|
||||
} finally {
|
||||
if (originalContext == null) {
|
||||
WallContext.clearContext();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public WallCheckResult checkInternal(String sql) {
|
||||
checkCount.incrementAndGet();
|
||||
|
||||
WallContext context = WallContext.current();
|
||||
|
||||
if (context != null && !this.dbType.equals(context.getDbType())) {
|
||||
@@ -265,14 +375,53 @@ public abstract class WallProvider {
|
||||
}
|
||||
|
||||
// first step, check whiteList
|
||||
WallSqlStat sqlStat = getWhiteSql(sql);
|
||||
if (sqlStat != null) {
|
||||
sqlStat.incrementAndGetExecuteCount();
|
||||
return result;
|
||||
{
|
||||
WallSqlStat sqlStat = getWhiteSql(sql);
|
||||
if (sqlStat != null) {
|
||||
whiteListHitCount.incrementAndGet();
|
||||
sqlStat.incrementAndGetExecuteCount();
|
||||
|
||||
if (sqlStat.getTableStats() != null) {
|
||||
for (Map.Entry<String, WallSqlTableStat> entry : sqlStat.getTableStats().entrySet()) {
|
||||
String tableName = entry.getKey();
|
||||
WallSqlTableStat sqlTableStat = entry.getValue();
|
||||
WallTableStat tableStat = getTableStat(tableName);
|
||||
if (tableStat != null) {
|
||||
tableStat.addSqlTableStat(sqlTableStat);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
// check black list
|
||||
{
|
||||
WallSqlStat sqlStat = getBlackSql(sql);
|
||||
if (sqlStat != null) {
|
||||
blackListHitCount.incrementAndGet();
|
||||
sqlStat.incrementAndGetExecuteCount();
|
||||
|
||||
if (sqlStat.getTableStats() != null) {
|
||||
for (Map.Entry<String, WallSqlTableStat> entry : sqlStat.getTableStats().entrySet()) {
|
||||
String tableName = entry.getKey();
|
||||
WallSqlTableStat sqlTableStat = entry.getValue();
|
||||
WallTableStat tableStat = getTableStat(tableName);
|
||||
if (tableStat != null) {
|
||||
tableStat.addSqlTableStat(sqlTableStat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<Violation> blackViolations = sqlStat.getViolations();
|
||||
|
||||
result.getViolations().addAll(blackViolations);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
SQLStatementParser parser = createParser(sql);
|
||||
parser.getLexer().setCommentHandler(WallCommentHandler.instance);
|
||||
|
||||
if (!config.isCommentAllow()) {
|
||||
parser.getLexer().setAllowComment(false); // deny comment
|
||||
@@ -283,49 +432,62 @@ public abstract class WallProvider {
|
||||
final Token lastToken = parser.getLexer().token();
|
||||
if (lastToken != Token.EOF) {
|
||||
result.getViolations().add(new IllegalSQLObjectViolation("not terminal sql, token " + lastToken, sql));
|
||||
return result;
|
||||
}
|
||||
} catch (NotAllowCommentException e) {
|
||||
result.getViolations().add(new SyntaxErrorViolation(e, sql));
|
||||
incrementCommentDeniedCount();
|
||||
return result;
|
||||
} catch (ParserException e) {
|
||||
syntaxErrrorCount.incrementAndGet();
|
||||
if (config.isStrictSyntaxCheck()) {
|
||||
result.getViolations().add(new SyntaxErrorViolation(e, sql));
|
||||
}
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
result.getViolations().add(new SyntaxErrorViolation(e, sql));
|
||||
return result;
|
||||
}
|
||||
|
||||
if (result.getStatementList().size() == 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (result.getStatementList().size() > 1 && !config.isMultiStatementAllow()) {
|
||||
if (result.getViolations().size() == 0 && result.getStatementList().size() > 1
|
||||
&& !config.isMultiStatementAllow()) {
|
||||
result.getViolations().add(new IllegalSQLObjectViolation("multi-statement not allow", sql));
|
||||
return result;
|
||||
}
|
||||
|
||||
SQLStatement stmt = result.getStatementList().get(0);
|
||||
|
||||
WallVisitor visitor = createWallVisitor();
|
||||
|
||||
try {
|
||||
stmt.accept(visitor);
|
||||
} catch (ParserException e) {
|
||||
result.getViolations().add(new SyntaxErrorViolation(e, sql));
|
||||
return result;
|
||||
if (result.getStatementList().size() > 0) {
|
||||
SQLStatement stmt = result.getStatementList().get(0);
|
||||
try {
|
||||
stmt.accept(visitor);
|
||||
} catch (ParserException e) {
|
||||
result.getViolations().add(new SyntaxErrorViolation(e, sql));
|
||||
}
|
||||
}
|
||||
|
||||
if (visitor.getViolations().size() == 0) {
|
||||
if (sql.length() < whiteSqlMaxLength) {
|
||||
this.addWhiteSql(sql);
|
||||
if (visitor.getViolations().size() > 0) {
|
||||
result.getViolations().addAll(visitor.getViolations());
|
||||
}
|
||||
|
||||
if (result.getViolations().size() > 0) {
|
||||
violationCount.incrementAndGet();
|
||||
|
||||
if (sql.length() < MAX_SQL_SIZE) {
|
||||
addBlackSql(sql, context.getTableStats(), result.getViolations());
|
||||
}
|
||||
} else {
|
||||
if (sql.length() < MAX_SQL_SIZE) {
|
||||
addWhiteSql(sql, context.getTableStats());
|
||||
}
|
||||
}
|
||||
|
||||
if (context != null && context.getTableStats() != null) {
|
||||
for (Map.Entry<String, WallSqlTableStat> entry : context.getTableStats().entrySet()) {
|
||||
String tableName = entry.getKey();
|
||||
WallSqlTableStat sqlTableStat = entry.getValue();
|
||||
WallTableStat tableStat = getTableStat(tableName);
|
||||
if (tableStat != null) {
|
||||
tableStat.addSqlTableStat(sqlTableStat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.getViolations().addAll(visitor.getViolations());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -356,4 +518,53 @@ public abstract class WallProvider {
|
||||
public static Object getTenantValue() {
|
||||
return tenantValueLocal.get();
|
||||
}
|
||||
|
||||
public long getWhiteListHitCount() {
|
||||
return whiteListHitCount.get();
|
||||
}
|
||||
|
||||
public long getBlackListHitCount() {
|
||||
return blackListHitCount.get();
|
||||
}
|
||||
|
||||
public long getSyntaxErrorCount() {
|
||||
return syntaxErrrorCount.get();
|
||||
}
|
||||
|
||||
public long getCheckCount() {
|
||||
return checkCount.get();
|
||||
}
|
||||
|
||||
public long getViolationCount() {
|
||||
return violationCount.get();
|
||||
}
|
||||
|
||||
public static class WallCommentHandler implements Lexer.CommentHandler {
|
||||
public final static WallCommentHandler instance = new WallCommentHandler();
|
||||
|
||||
@Override
|
||||
public boolean handle(Token lastToken, String comment) {
|
||||
if (lastToken == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (lastToken) {
|
||||
case SELECT:
|
||||
case INSERT:
|
||||
case DELETE:
|
||||
case UPDATE:
|
||||
case TRUNCATE:
|
||||
case SET:
|
||||
case CREATE:
|
||||
case ALTER:
|
||||
case DROP:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
*/
|
||||
package com.alibaba.druid.wall;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
|
||||
|
||||
public class WallSqlStat {
|
||||
@@ -23,6 +26,18 @@ public class WallSqlStat {
|
||||
|
||||
final static AtomicLongFieldUpdater<WallSqlStat> executeCountUpdater = AtomicLongFieldUpdater.newUpdater(WallSqlStat.class,
|
||||
"executeCount");
|
||||
private final Map<String, WallSqlTableStat> tableStats;
|
||||
|
||||
private final List<Violation> violations;
|
||||
|
||||
public WallSqlStat(Map<String, WallSqlTableStat> tableStats){
|
||||
this(tableStats, Collections.<Violation> emptyList());
|
||||
}
|
||||
|
||||
public WallSqlStat(Map<String, WallSqlTableStat> tableStats, List<Violation> violations){
|
||||
this.violations = violations;
|
||||
this.tableStats = tableStats;
|
||||
}
|
||||
|
||||
public long incrementAndGetExecuteCount() {
|
||||
return executeCountUpdater.incrementAndGet(this);
|
||||
@@ -31,5 +46,13 @@ public class WallSqlStat {
|
||||
public long getExecuteCount() {
|
||||
return executeCount;
|
||||
}
|
||||
|
||||
|
||||
public Map<String, WallSqlTableStat> getTableStats() {
|
||||
return tableStats;
|
||||
}
|
||||
|
||||
public List<Violation> getViolations() {
|
||||
return violations;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
package com.alibaba.druid.wall;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
public class WallSqlTableStat {
|
||||
|
||||
private int selectCount;
|
||||
private int selectIntoCount;
|
||||
private int insertCount;
|
||||
private int updateCount;
|
||||
private int deleteCount;
|
||||
private int truncateCount;
|
||||
private int createCount;
|
||||
private int alterCount;
|
||||
private int dropCount;
|
||||
|
||||
public int getSelectCount() {
|
||||
return selectCount;
|
||||
}
|
||||
|
||||
public void incrementSelectCount() {
|
||||
this.selectCount++;
|
||||
}
|
||||
|
||||
public int getSelectIntoCount() {
|
||||
return selectIntoCount;
|
||||
}
|
||||
|
||||
public void incrementSelectIntoCount() {
|
||||
this.selectIntoCount++;
|
||||
}
|
||||
|
||||
public int getInsertCount() {
|
||||
return insertCount;
|
||||
}
|
||||
|
||||
public void incrementInsertCount() {
|
||||
this.insertCount++;
|
||||
}
|
||||
|
||||
public int getUpdateCount() {
|
||||
return updateCount;
|
||||
}
|
||||
|
||||
public void incrementUpdateCount() {
|
||||
this.updateCount++;
|
||||
}
|
||||
|
||||
public int getDeleteCount() {
|
||||
return deleteCount;
|
||||
}
|
||||
|
||||
public void incrementDeleteCount() {
|
||||
this.deleteCount++;
|
||||
}
|
||||
|
||||
public int getTruncateCount() {
|
||||
return truncateCount;
|
||||
}
|
||||
|
||||
public void incrementTruncateCount() {
|
||||
this.truncateCount++;
|
||||
}
|
||||
|
||||
public int getCreateCount() {
|
||||
return createCount;
|
||||
}
|
||||
|
||||
public void incrementCreateCount() {
|
||||
this.createCount++;
|
||||
}
|
||||
|
||||
public int getAlterCount() {
|
||||
return alterCount;
|
||||
}
|
||||
|
||||
public void incrementAlterCount() {
|
||||
this.alterCount++;
|
||||
}
|
||||
|
||||
public int getDropCount() {
|
||||
return dropCount;
|
||||
}
|
||||
|
||||
public void incrementDropCount() {
|
||||
this.dropCount++;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
package com.alibaba.druid.wall;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicLongFieldUpdater;
|
||||
|
||||
import com.alibaba.druid.support.json.JSONUtils;
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
public class WallTableStat {
|
||||
|
||||
private volatile long selectCount;
|
||||
private volatile long selectIntoCount;
|
||||
private volatile long insertCount;
|
||||
private volatile long updateCount;
|
||||
private volatile long deleteCount;
|
||||
private volatile long truncateCount;
|
||||
private volatile long createCount;
|
||||
private volatile long alterCount;
|
||||
private volatile long dropCount;
|
||||
|
||||
final static AtomicLongFieldUpdater<WallTableStat> selectCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,
|
||||
"selectCount");
|
||||
final static AtomicLongFieldUpdater<WallTableStat> selectIntoCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,
|
||||
"selectIntoCount");
|
||||
final static AtomicLongFieldUpdater<WallTableStat> insertCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,
|
||||
"insertCount");
|
||||
final static AtomicLongFieldUpdater<WallTableStat> updateCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,
|
||||
"updateCount");
|
||||
final static AtomicLongFieldUpdater<WallTableStat> deleteCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,
|
||||
"deleteCount");
|
||||
final static AtomicLongFieldUpdater<WallTableStat> truncateCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,
|
||||
"truncateCount");
|
||||
final static AtomicLongFieldUpdater<WallTableStat> createCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,
|
||||
"createCount");
|
||||
final static AtomicLongFieldUpdater<WallTableStat> alterCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,
|
||||
"alterCount");
|
||||
final static AtomicLongFieldUpdater<WallTableStat> dropCountUpdater = AtomicLongFieldUpdater.newUpdater(WallTableStat.class,
|
||||
"dropCount");
|
||||
|
||||
public WallTableStat(){
|
||||
|
||||
}
|
||||
|
||||
public long getSelectCount() {
|
||||
return selectCount;
|
||||
}
|
||||
|
||||
public long getSelectIntoCount() {
|
||||
return selectIntoCount;
|
||||
}
|
||||
|
||||
public long getInsertCount() {
|
||||
return insertCount;
|
||||
}
|
||||
|
||||
public long getUpdateCount() {
|
||||
return updateCount;
|
||||
}
|
||||
|
||||
public long getDeleteCount() {
|
||||
return deleteCount;
|
||||
}
|
||||
|
||||
public long getTruncateCount() {
|
||||
return truncateCount;
|
||||
}
|
||||
|
||||
public long getCreateCount() {
|
||||
return createCount;
|
||||
}
|
||||
|
||||
public long getAlterCount() {
|
||||
return alterCount;
|
||||
}
|
||||
|
||||
public long getDropCount() {
|
||||
return dropCount;
|
||||
}
|
||||
|
||||
public void addSqlTableStat(WallSqlTableStat stat) {
|
||||
{
|
||||
long val = stat.getSelectCount();
|
||||
if (val > 0) {
|
||||
selectCountUpdater.addAndGet(this, val);
|
||||
}
|
||||
}
|
||||
{
|
||||
long val = stat.getSelectIntoCount();
|
||||
if (val > 0) {
|
||||
selectIntoCountUpdater.addAndGet(this, val);
|
||||
}
|
||||
}
|
||||
{
|
||||
long val = stat.getInsertCount();
|
||||
if (val > 0) {
|
||||
insertCountUpdater.addAndGet(this, val);
|
||||
}
|
||||
}
|
||||
{
|
||||
long val = stat.getUpdateCount();
|
||||
if (val > 0) {
|
||||
updateCountUpdater.addAndGet(this, val);
|
||||
}
|
||||
}
|
||||
{
|
||||
long val = stat.getDeleteCount();
|
||||
if (val > 0) {
|
||||
deleteCountUpdater.addAndGet(this, val);
|
||||
}
|
||||
}
|
||||
{
|
||||
long val = stat.getAlterCount();
|
||||
if (val > 0) {
|
||||
alterCountUpdater.addAndGet(this, val);
|
||||
}
|
||||
}
|
||||
{
|
||||
long val = stat.getTruncateCount();
|
||||
if (val > 0) {
|
||||
truncateCountUpdater.addAndGet(this, val);
|
||||
}
|
||||
}
|
||||
{
|
||||
long val = stat.getCreateCount();
|
||||
if (val > 0) {
|
||||
createCountUpdater.addAndGet(this, val);
|
||||
}
|
||||
}
|
||||
{
|
||||
long val = stat.getDropCount();
|
||||
if (val > 0) {
|
||||
dropCountUpdater.addAndGet(this, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
if (selectCount > 0) {
|
||||
map.put("selectCount", selectCount);
|
||||
}
|
||||
if (deleteCount > 0) {
|
||||
map.put("deleteCount", deleteCount);
|
||||
}
|
||||
if (insertCount > 0) {
|
||||
map.put("insertCount", insertCount);
|
||||
}
|
||||
if (updateCount > 0) {
|
||||
map.put("updateCount", updateCount);
|
||||
}
|
||||
if (alterCount > 0) {
|
||||
map.put("alterCount", alterCount);
|
||||
}
|
||||
if (dropCount > 0) {
|
||||
map.put("dropCount", dropCount);
|
||||
}
|
||||
if (createCount > 0) {
|
||||
map.put("createCount", createCount);
|
||||
}
|
||||
if (truncateCount > 0) {
|
||||
map.put("truncateCount", truncateCount);
|
||||
}
|
||||
|
||||
return JSONUtils.toJSONString(map);
|
||||
}
|
||||
}
|
||||
@@ -21,36 +21,33 @@ import java.util.List;
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLName;
|
||||
import com.alibaba.druid.sql.ast.SQLObject;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLInListExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLNumericLiteralExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLCallStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSetStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUnionQuery;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOutFileExpr;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlAlterTableStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDescribeStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDropTableStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlReplaceStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectGroupBy;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock.Limit;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSetCharSetStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSetNamesStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUnionQuery;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitor;
|
||||
@@ -190,6 +187,16 @@ public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisi
|
||||
}
|
||||
|
||||
if (config.isVariantCheck() && varName.startsWith("@@")) {
|
||||
if ("@@session".equals(varName)) {
|
||||
SQLObject parent = x.getParent();
|
||||
if (parent instanceof SQLPropertyExpr) {
|
||||
String propName = ((SQLPropertyExpr) parent).getName();
|
||||
if (propName.equals("auto_increment_increment")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
violations.add(new IllegalSQLObjectViolation("global variable", toSQL(x)));
|
||||
}
|
||||
|
||||
@@ -251,56 +258,7 @@ public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisi
|
||||
}
|
||||
|
||||
public void preVisit(SQLObject x) {
|
||||
if (!(x instanceof SQLStatement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean allow = false;
|
||||
String denyMessage = null;
|
||||
if (x instanceof SQLInsertStatement) {
|
||||
allow = true;
|
||||
denyMessage = "insert not allow";
|
||||
} else if (x instanceof SQLSelectStatement) {
|
||||
allow = true;
|
||||
denyMessage = "select not allow";
|
||||
} else if (x instanceof SQLDeleteStatement) {
|
||||
allow = true;
|
||||
denyMessage = "delete not allow";
|
||||
} else if (x instanceof SQLUpdateStatement) {
|
||||
allow = true;
|
||||
denyMessage = "update not allow";
|
||||
} else if (x instanceof SQLCallStatement) {
|
||||
allow = true;
|
||||
denyMessage = "call not allow";
|
||||
} else if (x instanceof SQLTruncateStatement) {
|
||||
allow = config.isTruncateAllow();
|
||||
denyMessage = "truncate not allow";
|
||||
} else if (x instanceof MySqlDescribeStatement) {
|
||||
allow = config.isDescribeAllow();
|
||||
denyMessage = "describe not allow";
|
||||
} else if (x instanceof MySqlReplaceStatement) {
|
||||
allow = config.isReplaceAllow();
|
||||
denyMessage = "replace not allow";
|
||||
} else if (x instanceof MySqlSetCharSetStatement //
|
||||
|| x instanceof MySqlSetNamesStatement //
|
||||
|| x instanceof SQLSetStatement) {
|
||||
allow = config.isSetAllow();
|
||||
denyMessage = "set not allow";
|
||||
} else if (x instanceof MySqlShowStatement) {
|
||||
allow = config.isShowAllow();
|
||||
denyMessage = "show not allow";
|
||||
} else {
|
||||
if (config.isNoneBaseStatementAllow()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!allow) {
|
||||
if (denyMessage == null) {
|
||||
denyMessage = x.getClass() + " not allow";
|
||||
}
|
||||
violations.add(new IllegalSQLObjectViolation(denyMessage + " not allow", toSQL(x)));
|
||||
}
|
||||
WallVisitorUtils.preVisitCheck(this, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -308,4 +266,38 @@ public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisi
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLCreateTableStatement x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(MySqlCreateTableStatement x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(SQLAlterTableStatement x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(MySqlAlterTableStatement x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(SQLDropTableStatement x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(MySqlDropTableStatement x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,26 +21,27 @@ import java.util.List;
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLName;
|
||||
import com.alibaba.druid.sql.ast.SQLObject;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
|
||||
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.SQLCallStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUnionQuery;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;
|
||||
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;
|
||||
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleInsertStatement;
|
||||
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement;
|
||||
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement;
|
||||
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.InsertIntoClause;
|
||||
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock;
|
||||
@@ -170,36 +171,7 @@ public class OracleWallVisitor extends OracleASTVisitorAdapter implements WallVi
|
||||
}
|
||||
|
||||
public void preVisit(SQLObject x) {
|
||||
if (!(x instanceof SQLStatement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (config.isNoneBaseStatementAllow()) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean allow = false;
|
||||
if (x instanceof SQLInsertStatement) {
|
||||
allow = true;
|
||||
} else if (x instanceof SQLSelectStatement) {
|
||||
allow = true;
|
||||
} else if (x instanceof SQLDeleteStatement) {
|
||||
allow = true;
|
||||
} else if (x instanceof SQLUpdateStatement) {
|
||||
allow = true;
|
||||
} else if (x instanceof OracleMultiInsertStatement) {
|
||||
allow = true;
|
||||
} else if (x instanceof OracleMergeStatement) {
|
||||
allow = true;
|
||||
} else if (x instanceof SQLCallStatement) {
|
||||
allow = true;
|
||||
} else if (x instanceof SQLTruncateStatement) {
|
||||
allow = config.isTruncateAllow();
|
||||
}
|
||||
|
||||
if (!allow) {
|
||||
violations.add(new IllegalSQLObjectViolation("not allow statement", toSQL(x)));
|
||||
}
|
||||
WallVisitorUtils.preVisitCheck(this, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -269,4 +241,34 @@ public class OracleWallVisitor extends OracleASTVisitorAdapter implements WallVi
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLCreateTableStatement x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(OracleCreateTableStatement x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLAlterTableStatement x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(OracleAlterTableStatement x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLDropTableStatement x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,26 +21,25 @@ import java.util.List;
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLName;
|
||||
import com.alibaba.druid.sql.ast.SQLObject;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
|
||||
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.SQLCallStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUnionQuery;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;
|
||||
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement;
|
||||
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement;
|
||||
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;
|
||||
import com.alibaba.druid.wall.Violation;
|
||||
import com.alibaba.druid.wall.WallConfig;
|
||||
@@ -131,6 +130,13 @@ public class PGWallVisitor extends PGASTVisitorAdapter implements WallVisitor {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(PGSelectQueryBlock x) {
|
||||
WallVisitorUtils.checkSelelct(this, x);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLUnionQuery x) {
|
||||
@@ -158,36 +164,7 @@ public class PGWallVisitor extends PGASTVisitorAdapter implements WallVisitor {
|
||||
}
|
||||
|
||||
public void preVisit(SQLObject x) {
|
||||
if (!(x instanceof SQLStatement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (config.isNoneBaseStatementAllow()) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean allow = false;
|
||||
if (x instanceof SQLInsertStatement) {
|
||||
allow = true;
|
||||
} else if (x instanceof SQLSelectStatement) {
|
||||
allow = true;
|
||||
} else if (x instanceof SQLDeleteStatement) {
|
||||
allow = true;
|
||||
} else if (x instanceof SQLUpdateStatement) {
|
||||
allow = true;
|
||||
} else if (x instanceof OracleMultiInsertStatement) {
|
||||
allow = true;
|
||||
} else if (x instanceof OracleMergeStatement) {
|
||||
allow = true;
|
||||
} else if (x instanceof SQLCallStatement) {
|
||||
allow = true;
|
||||
} else if (x instanceof SQLTruncateStatement) {
|
||||
allow = config.isTruncateAllow();
|
||||
}
|
||||
|
||||
if (!allow) {
|
||||
violations.add(new IllegalSQLObjectViolation("not allow statement", toSQL(x)));
|
||||
}
|
||||
WallVisitorUtils.preVisitCheck(this, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -225,4 +202,22 @@ public class PGWallVisitor extends PGASTVisitorAdapter implements WallVisitor {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLCreateTableStatement x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLAlterTableStatement x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLDropTableStatement x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,22 +21,22 @@ import java.util.List;
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLName;
|
||||
import com.alibaba.druid.sql.ast.SQLObject;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
|
||||
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.expr.SQLVariantRefExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLCallStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUnionQuery;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;
|
||||
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock;
|
||||
@@ -161,32 +161,7 @@ public class SQLServerWallVisitor extends SQLServerASTVisitorAdapter implements
|
||||
}
|
||||
|
||||
public void preVisit(SQLObject x) {
|
||||
if (!(x instanceof SQLStatement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (config.isNoneBaseStatementAllow()) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean allow = false;
|
||||
if (x instanceof SQLInsertStatement) {
|
||||
allow = true;
|
||||
} else if (x instanceof SQLSelectStatement) {
|
||||
allow = true;
|
||||
} else if (x instanceof SQLDeleteStatement) {
|
||||
allow = true;
|
||||
} else if (x instanceof SQLUpdateStatement) {
|
||||
allow = true;
|
||||
} else if (x instanceof SQLCallStatement) {
|
||||
allow = true;
|
||||
} else if (x instanceof SQLTruncateStatement) {
|
||||
allow = config.isTruncateAllow();
|
||||
}
|
||||
|
||||
if (!allow) {
|
||||
violations.add(new IllegalSQLObjectViolation("not allow statement", toSQL(x)));
|
||||
}
|
||||
WallVisitorUtils.preVisitCheck(this, x);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -201,11 +176,7 @@ public class SQLServerWallVisitor extends SQLServerASTVisitorAdapter implements
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLInsertStatement x) {
|
||||
if (!config.isInsertAllow()) {
|
||||
this.getViolations().add(new IllegalSQLObjectViolation("insert not allow", this.toSQL(x)));
|
||||
return false;
|
||||
}
|
||||
|
||||
WallVisitorUtils.checkInsert(this, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -249,8 +220,7 @@ public class SQLServerWallVisitor extends SQLServerASTVisitorAdapter implements
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLServerInsertStatement x) {
|
||||
this.visit((SQLInsertStatement) x);
|
||||
return false;
|
||||
return this.visit((SQLInsertStatement) x);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -263,4 +233,22 @@ public class SQLServerWallVisitor extends SQLServerASTVisitorAdapter implements
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLCreateTableStatement x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLAlterTableStatement x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLDropTableStatement x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import java.util.Set;
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLName;
|
||||
import com.alibaba.druid.sql.ast.SQLObject;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLAggregateExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
|
||||
@@ -44,29 +45,46 @@ import com.alibaba.druid.sql.ast.expr.SQLNumberExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLNumericLiteralExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
|
||||
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;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLInsertInto;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelect;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSetStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
|
||||
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.dialect.mysql.ast.expr.MySqlBooleanExpr;
|
||||
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;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSetNamesStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement;
|
||||
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMergeStatement;
|
||||
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement;
|
||||
import com.alibaba.druid.sql.visitor.ExportParameterVisitor;
|
||||
import com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;
|
||||
import com.alibaba.druid.support.logging.Log;
|
||||
import com.alibaba.druid.support.logging.LogFactory;
|
||||
import com.alibaba.druid.util.JdbcUtils;
|
||||
import com.alibaba.druid.util.ServletPathMatcher;
|
||||
import com.alibaba.druid.wall.WallConfig;
|
||||
import com.alibaba.druid.wall.WallContext;
|
||||
import com.alibaba.druid.wall.WallProvider;
|
||||
import com.alibaba.druid.wall.WallSqlTableStat;
|
||||
import com.alibaba.druid.wall.WallVisitor;
|
||||
import com.alibaba.druid.wall.violation.IllegalSQLObjectViolation;
|
||||
|
||||
@@ -82,6 +100,44 @@ public class WallVisitorUtils {
|
||||
|
||||
}
|
||||
|
||||
public static void check(WallVisitor visitor, SQLCreateTableStatement x) {
|
||||
String tableName = ((SQLName) x.getName()).getSimleName();
|
||||
WallContext context = WallContext.current();
|
||||
if (context != null) {
|
||||
WallSqlTableStat tableStat = context.getTableStat(tableName);
|
||||
if (tableStat != null) {
|
||||
tableStat.incrementCreateCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void check(WallVisitor visitor, SQLAlterTableStatement x) {
|
||||
String tableName = ((SQLName) x.getName()).getSimleName();
|
||||
WallContext context = WallContext.current();
|
||||
if (context != null) {
|
||||
WallSqlTableStat tableStat = context.getTableStat(tableName);
|
||||
if (tableStat != null) {
|
||||
tableStat.incrementAlterCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void check(WallVisitor visitor, SQLDropTableStatement x) {
|
||||
for (SQLTableSource item : x.getTableSources()) {
|
||||
if (item instanceof SQLExprTableSource) {
|
||||
SQLExpr expr = ((SQLExprTableSource) item).getExpr();
|
||||
String tableName = ((SQLName) expr).getSimleName();
|
||||
WallContext context = WallContext.current();
|
||||
if (context != null) {
|
||||
WallSqlTableStat tableStat = context.getTableStat(tableName);
|
||||
if (tableStat != null) {
|
||||
tableStat.incrementDropCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void check(WallVisitor visitor, SQLSelectItem x) {
|
||||
if (visitor.getConfig().isSelectAllColumnAllow()) {
|
||||
return;
|
||||
@@ -124,6 +180,10 @@ public class WallVisitorUtils {
|
||||
return;
|
||||
}
|
||||
|
||||
if (x.getFrom() != null) {
|
||||
x.getFrom().setParent(x);
|
||||
}
|
||||
|
||||
SQLExpr where = x.getWhere();
|
||||
|
||||
if (where != null) {
|
||||
@@ -777,6 +837,36 @@ public class WallVisitorUtils {
|
||||
|
||||
if (expr instanceof SQLName) {
|
||||
String tableName = ((SQLName) expr).getSimleName();
|
||||
|
||||
WallContext context = WallContext.current();
|
||||
if (context != null) {
|
||||
WallSqlTableStat tableStat = context.getTableStat(tableName);
|
||||
if (tableStat != null) {
|
||||
SQLObject parent = x.getParent();
|
||||
|
||||
while (parent instanceof SQLTableSource) {
|
||||
parent = parent.getParent();
|
||||
}
|
||||
|
||||
if (parent instanceof SQLSelectQueryBlock) {
|
||||
SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock) parent;
|
||||
if (x == queryBlock.getInto()) {
|
||||
tableStat.incrementSelectIntoCount();
|
||||
} else {
|
||||
tableStat.incrementSelectCount();
|
||||
}
|
||||
} else if (parent instanceof SQLTruncateStatement) {
|
||||
tableStat.incrementTruncateCount();
|
||||
} else if (parent instanceof SQLInsertStatement) {
|
||||
tableStat.incrementInsertCount();
|
||||
} else if (parent instanceof SQLDeleteStatement) {
|
||||
tableStat.incrementDeleteCount();
|
||||
} else if (parent instanceof SQLUpdateStatement) {
|
||||
tableStat.incrementUpdateCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (visitor.isDenyTable(tableName)) {
|
||||
addViolation(visitor, "deny table : " + tableName, x);
|
||||
return false;
|
||||
@@ -901,4 +991,72 @@ public class WallVisitorUtils {
|
||||
LOG.error("load oracle deny tables errror", e);
|
||||
}
|
||||
}
|
||||
|
||||
public static void preVisitCheck(WallVisitor visitor, SQLObject x) {
|
||||
WallConfig config = visitor.getProvider().getConfig();
|
||||
|
||||
if (!(x instanceof SQLStatement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean allow = false;
|
||||
String denyMessage = null;
|
||||
if (x instanceof SQLInsertStatement) {
|
||||
allow = true;
|
||||
denyMessage = "insert not allow";
|
||||
} else if (x instanceof SQLSelectStatement) {
|
||||
allow = true;
|
||||
denyMessage = "select not allow";
|
||||
} else if (x instanceof SQLDeleteStatement) {
|
||||
allow = true;
|
||||
denyMessage = "delete not allow";
|
||||
} else if (x instanceof SQLUpdateStatement) {
|
||||
allow = true;
|
||||
denyMessage = "update not allow";
|
||||
} else if (x instanceof OracleMultiInsertStatement) {
|
||||
allow = true;
|
||||
denyMessage = "multi-insert not allow";
|
||||
} else if (x instanceof OracleMergeStatement) {
|
||||
allow = true;
|
||||
denyMessage = "merge not allow";
|
||||
} else if (x instanceof SQLCallStatement) {
|
||||
allow = true;
|
||||
denyMessage = "call not allow";
|
||||
} else if (x instanceof SQLTruncateStatement) {
|
||||
allow = config.isTruncateAllow();
|
||||
denyMessage = "truncate not allow";
|
||||
} else if (x instanceof SQLCreateTableStatement) {
|
||||
allow = config.isCreateTableAllow();
|
||||
denyMessage = "create table not allow";
|
||||
} else if (x instanceof SQLAlterTableStatement) {
|
||||
allow = config.isAlterTableAllow();
|
||||
denyMessage = "alter table not allow";
|
||||
} else if (x instanceof SQLDropTableStatement) {
|
||||
allow = config.isDropTableAllow();
|
||||
denyMessage = "drop table not allow";
|
||||
} else if (x instanceof MySqlSetCharSetStatement //
|
||||
|| x instanceof MySqlSetNamesStatement //
|
||||
|| x instanceof SQLSetStatement) {
|
||||
allow = config.isSetAllow();
|
||||
denyMessage = "set not allow";
|
||||
} else if (x instanceof MySqlReplaceStatement) {
|
||||
allow = config.isReplaceAllow();
|
||||
denyMessage = "replace not allow";
|
||||
} else if (x instanceof MySqlDescribeStatement) {
|
||||
allow = config.isDescribeAllow();
|
||||
denyMessage = "describe not allow";
|
||||
} else if (x instanceof MySqlShowStatement) {
|
||||
allow = config.isShowAllow();
|
||||
denyMessage = "show not allow";
|
||||
} else {
|
||||
allow = config.isNoneBaseStatementAllow();
|
||||
}
|
||||
|
||||
if (!allow) {
|
||||
if (denyMessage == null) {
|
||||
denyMessage = x.getClass() + " not allow";
|
||||
}
|
||||
addViolation(visitor, denyMessage, x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user