diff --git a/src/main/java/com/alibaba/druid/filter/wall/IllegalConditionViolation.java b/src/main/java/com/alibaba/druid/filter/wall/IllegalConditionViolation.java new file mode 100644 index 0000000000..c9477e6ca2 --- /dev/null +++ b/src/main/java/com/alibaba/druid/filter/wall/IllegalConditionViolation.java @@ -0,0 +1,23 @@ +package com.alibaba.druid.filter.wall; + +public class IllegalConditionViolation implements Violation { + + private String condition; + + public IllegalConditionViolation(){ + + } + + public IllegalConditionViolation(String condition){ + this.condition = condition; + } + + public String getCondition() { + return condition; + } + + public void setCondition(String condition) { + this.condition = condition; + } + +} diff --git a/src/main/java/com/alibaba/druid/filter/wall/IllegalStatementViolation.java b/src/main/java/com/alibaba/druid/filter/wall/IllegalStatementViolation.java new file mode 100644 index 0000000000..05bcabbb80 --- /dev/null +++ b/src/main/java/com/alibaba/druid/filter/wall/IllegalStatementViolation.java @@ -0,0 +1,23 @@ +package com.alibaba.druid.filter.wall; + +public class IllegalStatementViolation implements Violation { + + private String condition; + + public IllegalStatementViolation(){ + + } + + public IllegalStatementViolation(String condition){ + this.condition = condition; + } + + public String getCondition() { + return condition; + } + + public void setCondition(String condition) { + this.condition = condition; + } + +} diff --git a/src/main/java/com/alibaba/druid/filter/wall/MySqlWallVisitor.java b/src/main/java/com/alibaba/druid/filter/wall/MySqlWallVisitor.java new file mode 100644 index 0000000000..bba0bfa773 --- /dev/null +++ b/src/main/java/com/alibaba/druid/filter/wall/MySqlWallVisitor.java @@ -0,0 +1,28 @@ +package com.alibaba.druid.filter.wall; + +import java.util.ArrayList; +import java.util.List; + +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlExecuteStatement; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter; + +public class MySqlWallVisitor extends MySqlASTVisitorAdapter { + + private final List violations; + + public MySqlWallVisitor() { + this(new ArrayList()); + } + + public MySqlWallVisitor(List violations) { + this.violations = violations; + } + + public List getViolations() { + return violations; + } + + public boolean visit(MySqlExecuteStatement x) { + return false; + } +} diff --git a/src/main/java/com/alibaba/druid/filter/wall/OracleWallVisitor.java b/src/main/java/com/alibaba/druid/filter/wall/OracleWallVisitor.java index 210e14fcf9..ed09a68615 100644 --- a/src/main/java/com/alibaba/druid/filter/wall/OracleWallVisitor.java +++ b/src/main/java/com/alibaba/druid/filter/wall/OracleWallVisitor.java @@ -1,8 +1,30 @@ package com.alibaba.druid.filter.wall; -import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVIsitorAdapter; +import java.util.ArrayList; +import java.util.List; +import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; +import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVIsitorAdapter; public class OracleWallVisitor extends OracleASTVIsitorAdapter implements WallVisitor { + private final List violations; + + public OracleWallVisitor(){ + this(new ArrayList()); + } + + public OracleWallVisitor(List violations){ + this.violations = violations; + } + + public List getViolations() { + return violations; + } + + public boolean visit(SQLBinaryOpExpr x) { + WallVisitorUtils.check(this, x); + + return true; + } } diff --git a/src/main/java/com/alibaba/druid/filter/wall/Violation.java b/src/main/java/com/alibaba/druid/filter/wall/Violation.java new file mode 100644 index 0000000000..d9b6192f23 --- /dev/null +++ b/src/main/java/com/alibaba/druid/filter/wall/Violation.java @@ -0,0 +1,6 @@ +package com.alibaba.druid.filter.wall; + + +public interface Violation { + +} diff --git a/src/main/java/com/alibaba/druid/filter/wall/WallFilter.java b/src/main/java/com/alibaba/druid/filter/wall/WallFilter.java index 8bfddebc46..975909bbc3 100644 --- a/src/main/java/com/alibaba/druid/filter/wall/WallFilter.java +++ b/src/main/java/com/alibaba/druid/filter/wall/WallFilter.java @@ -1,12 +1,15 @@ package com.alibaba.druid.filter.wall; import java.sql.SQLException; +import java.util.List; +import java.util.Properties; import com.alibaba.druid.filter.FilterAdapter; import com.alibaba.druid.filter.FilterChain; import com.alibaba.druid.proxy.jdbc.CallableStatementProxy; import com.alibaba.druid.proxy.jdbc.ConnectionProxy; import com.alibaba.druid.proxy.jdbc.PreparedStatementProxy; +import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; import com.alibaba.druid.sql.dialect.postgresql.parser.PGSQLStatementParser; @@ -17,15 +20,22 @@ import com.alibaba.druid.util.JdbcUtils; public class WallFilter extends FilterAdapter { + @Override + public ConnectionProxy connection_connect(FilterChain chain, Properties info) throws SQLException { + return chain.connection_connect(info); + } + @Override public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql) throws SQLException { + check(connection, sql); return chain.connection_prepareStatement(connection, sql); } @Override public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql, int autoGeneratedKeys) throws SQLException { + check(connection, sql); return chain.connection_prepareStatement(connection, sql, autoGeneratedKeys); } @@ -33,6 +43,7 @@ public class WallFilter extends FilterAdapter { public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql, int resultSetType, int resultSetConcurrency) throws SQLException { + check(connection, sql); return chain.connection_prepareStatement(connection, sql, resultSetType, resultSetConcurrency); } @@ -40,6 +51,7 @@ public class WallFilter extends FilterAdapter { public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { + check(connection, sql); return chain.connection_prepareStatement(connection, sql, resultSetType, resultSetConcurrency, resultSetHoldability); } @@ -47,18 +59,21 @@ public class WallFilter extends FilterAdapter { @Override public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql, int[] columnIndexes) throws SQLException { + check(connection, sql); return chain.connection_prepareStatement(connection, sql, columnIndexes); } @Override public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql, String[] columnNames) throws SQLException { + check(connection, sql); return chain.connection_prepareStatement(connection, sql, columnNames); } @Override public CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection, String sql) throws SQLException { + check(connection, sql); return chain.connection_prepareCall(connection, sql); } @@ -66,6 +81,7 @@ public class WallFilter extends FilterAdapter { public CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection, String sql, int resultSetType, int resultSetConcurrency) throws SQLException { + check(connection, sql); return chain.connection_prepareCall(connection, sql, resultSetType, resultSetConcurrency); } @@ -73,9 +89,27 @@ public class WallFilter extends FilterAdapter { public CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection, String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { + check(connection, sql); return chain.connection_prepareCall(connection, sql, resultSetType, resultSetConcurrency, resultSetHoldability); } + public void check(ConnectionProxy connection, String sql) throws SQLException { + String dbType = connection.getDirectDataSource().getDbType(); + + SQLStatementParser parser = createParser(dbType, sql); + + List statementList = parser.parseStatementList(); + if (statementList.size() > 1) { + throw new SQLException("multi-statement : " + sql); + } + + SQLStatement stmt = statementList.get(0); + + SQLASTVisitor visitor = createWallVisitor(dbType); + + stmt.accept(visitor); + } + public SQLASTVisitor createWallVisitor(String dbType) throws SQLException { throw new SQLException("dbType not support : " + dbType); } diff --git a/src/main/java/com/alibaba/druid/filter/wall/WallVisitor.java b/src/main/java/com/alibaba/druid/filter/wall/WallVisitor.java index b85a235e43..d524d78250 100644 --- a/src/main/java/com/alibaba/druid/filter/wall/WallVisitor.java +++ b/src/main/java/com/alibaba/druid/filter/wall/WallVisitor.java @@ -1,8 +1,10 @@ package com.alibaba.druid.filter.wall; +import java.util.List; + import com.alibaba.druid.sql.visitor.SQLASTVisitor; - public interface WallVisitor extends SQLASTVisitor { + List getViolations(); } diff --git a/src/main/java/com/alibaba/druid/filter/wall/WallVisitorUtils.java b/src/main/java/com/alibaba/druid/filter/wall/WallVisitorUtils.java new file mode 100644 index 0000000000..66cac99fc6 --- /dev/null +++ b/src/main/java/com/alibaba/druid/filter/wall/WallVisitorUtils.java @@ -0,0 +1,29 @@ +package com.alibaba.druid.filter.wall; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; +import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator; +import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr; + +public class WallVisitorUtils { + + public static void check(WallVisitor visitor, 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()); + + if (!leftLiteral.equalsIgnoreCase(rightLiteral)) { + visitor.getViolations().add(new IllegalConditionViolation(SQLUtils.toOracleString(x))); + } + } + } + } +}