add sql wall support

This commit is contained in:
温少
2012-03-14 23:30:55 +08:00
parent e4927358c0
commit 9707e2fb23
5 changed files with 181 additions and 19 deletions
@@ -4,10 +4,14 @@ import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.filter.wall.Violation;
import com.alibaba.druid.filter.wall.WallVisitor;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlExecuteStatement;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter;
public class MySqlWallVisitor extends MySqlASTVisitorAdapter {
public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisitor {
private final List<Violation> violations;
@@ -26,4 +30,24 @@ public class MySqlWallVisitor extends MySqlASTVisitorAdapter {
public boolean visit(MySqlExecuteStatement x) {
return false;
}
public boolean visit(SQLBinaryOpExpr x) {
WallVisitorUtils.check(this, x);
return true;
}
@Override
public boolean visit(SQLSelectQueryBlock x) {
if (x.getWhere() != null) {
x.getWhere().setParent(x);
}
return true;
}
@Override
public boolean visit(MySqlSelectQueryBlock x) {
return visit((SQLSelectQueryBlock) x);
}
}
@@ -3,29 +3,100 @@ package com.alibaba.druid.filter.wall.spi;
import com.alibaba.druid.filter.wall.IllegalConditionViolation;
import com.alibaba.druid.filter.wall.WallVisitor;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;
import com.alibaba.druid.sql.ast.expr.SQLNotExpr;
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlBooleanExpr;
public class WallVisitorUtils {
public static void check(WallVisitor visitor, SQLBinaryOpExpr x) {
if (Boolean.TRUE == getObject(x)) {
visitor.getViolations().add(new IllegalConditionViolation(SQLUtils.toSQLString(x)));
}
}
public static Object getObject(SQLBinaryOpExpr x) {
if (x.getLeft() instanceof SQLLiteralExpr && x.getRight() instanceof SQLLiteralExpr) {
if (x.getOperator() == SQLBinaryOperator.Equality) {
String leftLiteral = SQLUtils.toOracleString(x.getLeft());
String rightLiteral = SQLUtils.toOracleString(x.getRight());
if (leftLiteral.equalsIgnoreCase(rightLiteral)) {
visitor.getViolations().add(new IllegalConditionViolation(SQLUtils.toOracleString(x)));
}
} else if (x.getOperator() == SQLBinaryOperator.NotEqual) {
String leftLiteral = SQLUtils.toOracleString(x.getLeft());
String rightLiteral = SQLUtils.toOracleString(x.getRight());
return leftLiteral.equalsIgnoreCase(rightLiteral);
}
if (!leftLiteral.equalsIgnoreCase(rightLiteral)) {
visitor.getViolations().add(new IllegalConditionViolation(SQLUtils.toOracleString(x)));
}
if (x.getOperator() == SQLBinaryOperator.NotEqual || x.getOperator() == SQLBinaryOperator.LessThanOrGreater) {
String leftLiteral = SQLUtils.toSQLString(x.getLeft());
String rightLiteral = SQLUtils.toSQLString(x.getRight());
return !leftLiteral.equalsIgnoreCase(rightLiteral);
}
}
if (x.getOperator() == SQLBinaryOperator.Like) {
if (x.getRight() instanceof SQLCharExpr) {
String text = ((SQLCharExpr) x.getRight()).getText();
if (text.length() >= 0) {
for (char ch : text.toCharArray()) {
if (ch != '%') {
return null;
}
}
return true;
}
}
}
x.getLeft().setParent(x);
x.getRight().setParent(x);
if (x.getOperator() == SQLBinaryOperator.BooleanOr) {
Object leftResult = getValue(x.getLeft());
Object rightResult = getValue(x.getRight());
if (Boolean.TRUE == leftResult || Boolean.TRUE == rightResult) {
return true;
}
}
if (x.getOperator() == SQLBinaryOperator.BooleanAnd) {
Object leftResult = getValue(x.getLeft());
Object rightResult = getValue(x.getRight());
if (Boolean.FALSE == leftResult || Boolean.FALSE == rightResult) {
return false;
}
if (Boolean.TRUE == leftResult && Boolean.TRUE == rightResult) {
return true;
}
}
return null;
}
public static Object getValue(SQLExpr x) {
if (x instanceof SQLBinaryOpExpr) {
return getObject((SQLBinaryOpExpr) x);
}
if (x instanceof MySqlBooleanExpr) {
return ((MySqlBooleanExpr) x).getValue();
}
if (x instanceof SQLNotExpr) {
Object result = getValue(((SQLNotExpr) x).getExpr());
if (result != null && result instanceof Boolean) {
return !((Boolean) result).booleanValue();
}
}
return null;
}
}
@@ -2,17 +2,32 @@ package com.alibaba.druid.sql;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLObject;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlExprParser;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlLexer;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor;
import com.alibaba.druid.sql.dialect.postgresql.parser.PGSQLStatementParser;
import com.alibaba.druid.sql.dialect.postgresql.visitor.PGOutputVisitor;
import com.alibaba.druid.sql.parser.ParserException;
import com.alibaba.druid.sql.parser.SQLExprParser;
import com.alibaba.druid.sql.parser.Token;
import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;
public class SQLUtils {
public static String toSQLString(SQLObject sqlObject) {
StringBuilder out = new StringBuilder();
sqlObject.accept(new SQLASTOutputVisitor(out));
String sql = out.toString();
return sql;
}
public static String toMySqlString(SQLObject sqlObject) {
StringBuilder out = new StringBuilder();
sqlObject.accept(new MySqlOutputVisitor(out));
@@ -20,14 +35,28 @@ public class SQLUtils {
String sql = out.toString();
return sql;
}
public static SQLExpr toMySqlExpr(String sql) {
MySqlLexer lexer = new MySqlLexer(sql);
lexer.nextToken();
MySqlExprParser parser = new MySqlExprParser(lexer);
SQLExpr expr = parser.expr();
if (lexer.token() != Token.EOF) {
throw new ParserException("illegal sql expr : " + sql);
}
return expr;
}
public static String formatMySql(String sql) {
MySqlStatementParser parser = new MySqlStatementParser(sql);
List<SQLStatement> statementList = parser.parseStatementList();
StringBuilder out = new StringBuilder();
MySqlOutputVisitor visitor = new MySqlOutputVisitor(out);
for (SQLStatement stmt : statementList) {
stmt.accept(visitor);
}
@@ -40,15 +69,15 @@ public class SQLUtils {
List<SQLStatement> statementList = parser.parseStatementList();
StringBuilder out = new StringBuilder();
OracleOutputVisitor visitor;
if (statementList.size() == 1) {
visitor = new OracleOutputVisitor(out, false);
} else {
visitor = new OracleOutputVisitor(out, true);
}
for (SQLStatement stmt : statementList) {
stmt.accept(visitor);
}
@@ -75,14 +104,28 @@ public class SQLUtils {
public static String formatPGSql(String sql) {
PGSQLStatementParser parser = new PGSQLStatementParser(sql);
List<SQLStatement> statementList = parser.parseStatementList();
StringBuilder out = new StringBuilder();
PGOutputVisitor visitor = new PGOutputVisitor(out);
for (SQLStatement stmt : statementList) {
stmt.accept(visitor);
}
return out.toString();
}
public static SQLExpr toSQLExpr(String sql) {
MySqlLexer lexer = new MySqlLexer(sql);
lexer.nextToken();
SQLExprParser parser = new SQLExprParser(lexer);
SQLExpr expr = parser.expr();
if (lexer.token() != Token.EOF) {
throw new ParserException("illegal sql expr : " + sql);
}
return expr;
}
}
@@ -275,7 +275,7 @@ public class SQLExprParser extends SQLParser {
accept(Token.RPAREN);
return primaryRest(sqlExpr);
} else {
SQLExpr restExpr = primary();
SQLExpr restExpr = expr();
sqlExpr = new SQLNotExpr(restExpr);
}
break;
@@ -0,0 +1,24 @@
package com.alibaba.druid.bvt.filter.wall;
import junit.framework.Assert;
import junit.framework.TestCase;
import com.alibaba.druid.filter.wall.spi.WallVisitorUtils;
import com.alibaba.druid.sql.SQLUtils;
public class WallVisitorUtilsTest extends TestCase {
public void test_isTrue() throws Exception {
Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("1 != 2")));
Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("1 != 2 AND 2 = 2")));
Assert.assertEquals(Boolean.FALSE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("1 != 2 AND 2 != 2")));
Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("23 = 23")));
Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("NOT 23 != 23")));
Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("f1 like '%'")));
Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("f1 like '%%'")));
Assert.assertEquals(null, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("a1 = b1 AND f1 like '%%'")));
Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("a1 = b1 OR f1 like '%%'")));
Assert.assertEquals(Boolean.TRUE, WallVisitorUtils.getValue(SQLUtils.toSQLExpr("1 < 2")));
}
}