mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
wall filter refactor
This commit is contained in:
@@ -145,14 +145,7 @@ public class SQLUtils {
|
||||
try {
|
||||
List<SQLStatement> statementList = toStatementList(sql, dbType);
|
||||
|
||||
StringBuilder out = new StringBuilder();
|
||||
SQLASTOutputVisitor visitor = createFormatOutputVisitor(out, statementList, dbType);
|
||||
|
||||
for (SQLStatement stmt : statementList) {
|
||||
stmt.accept(visitor);
|
||||
}
|
||||
|
||||
return out.toString();
|
||||
return toSQLString(statementList, dbType);
|
||||
} catch (SQLParseException ex) {
|
||||
LOG.warn("format error", ex);
|
||||
return sql;
|
||||
@@ -162,6 +155,17 @@ public class SQLUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static String toSQLString(List<SQLStatement> statementList, String dbType) {
|
||||
StringBuilder out = new StringBuilder();
|
||||
SQLASTOutputVisitor visitor = createFormatOutputVisitor(out, statementList, dbType);
|
||||
|
||||
for (SQLStatement stmt : statementList) {
|
||||
stmt.accept(visitor);
|
||||
}
|
||||
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
public static SQLASTOutputVisitor createFormatOutputVisitor(Appendable out, List<SQLStatement> statementList,
|
||||
String dbType) {
|
||||
if (JdbcUtils.ORACLE.equals(dbType) || JdbcUtils.ALI_ORACLE.equals(dbType)) {
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.alibaba.druid.wall;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
|
||||
public class WallCheckResult {
|
||||
|
||||
private final List<Violation> violations = new ArrayList<Violation>(2);
|
||||
private final List<SQLStatement> statementList = new ArrayList<SQLStatement>(2);
|
||||
|
||||
public WallCheckResult(){
|
||||
|
||||
}
|
||||
|
||||
public WallCheckResult(Violation violation){
|
||||
this.violations.add(violation);
|
||||
}
|
||||
|
||||
public List<Violation> getViolations() {
|
||||
return violations;
|
||||
}
|
||||
|
||||
public List<SQLStatement> getStatementList() {
|
||||
return statementList;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -71,10 +71,29 @@ public class WallConfig implements WallConfigMBean {
|
||||
|
||||
private boolean inited;
|
||||
|
||||
private String guardTablePattern;
|
||||
private String guardField;
|
||||
|
||||
public WallConfig(){
|
||||
|
||||
}
|
||||
|
||||
public String getGuardTablePattern() {
|
||||
return guardTablePattern;
|
||||
}
|
||||
|
||||
public void setGuardTablePattern(String guardTablePattern) {
|
||||
this.guardTablePattern = guardTablePattern;
|
||||
}
|
||||
|
||||
public String getGuardField() {
|
||||
return guardField;
|
||||
}
|
||||
|
||||
public void setGuardField(String guardField) {
|
||||
this.guardField = guardField;
|
||||
}
|
||||
|
||||
public boolean isAllowDoPrivileged() {
|
||||
return allowDoPrivileged;
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean {
|
||||
this.dbType = JdbcUtils.getDbType(dataSource.getRawJdbcUrl(), "");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (dbType == null) {
|
||||
dbType = JdbcUtils.getDbType(dataSource.getUrl(), null);
|
||||
}
|
||||
@@ -153,21 +153,21 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean {
|
||||
|
||||
@Override
|
||||
public void statement_addBatch(FilterChain chain, StatementProxy statement, String sql) throws SQLException {
|
||||
check(sql);
|
||||
sql = check(sql);
|
||||
chain.statement_addBatch(statement, sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql)
|
||||
throws SQLException {
|
||||
check(sql);
|
||||
sql = check(sql);
|
||||
return chain.connection_prepareStatement(connection, sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,
|
||||
String sql, int autoGeneratedKeys) throws SQLException {
|
||||
check(sql);
|
||||
sql = check(sql);
|
||||
return chain.connection_prepareStatement(connection, sql, autoGeneratedKeys);
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean {
|
||||
public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,
|
||||
String sql, int resultSetType, int resultSetConcurrency)
|
||||
throws SQLException {
|
||||
check(sql);
|
||||
sql = check(sql);
|
||||
return chain.connection_prepareStatement(connection, sql, resultSetType, resultSetConcurrency);
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean {
|
||||
public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,
|
||||
String sql, int resultSetType, int resultSetConcurrency,
|
||||
int resultSetHoldability) throws SQLException {
|
||||
check(sql);
|
||||
sql = check(sql);
|
||||
return chain.connection_prepareStatement(connection, sql, resultSetType, resultSetConcurrency,
|
||||
resultSetHoldability);
|
||||
}
|
||||
@@ -191,21 +191,21 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean {
|
||||
@Override
|
||||
public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,
|
||||
String sql, int[] columnIndexes) throws SQLException {
|
||||
check(sql);
|
||||
sql = check(sql);
|
||||
return chain.connection_prepareStatement(connection, sql, columnIndexes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection,
|
||||
String sql, String[] columnNames) throws SQLException {
|
||||
check(sql);
|
||||
sql = check(sql);
|
||||
return chain.connection_prepareStatement(connection, sql, columnNames);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection, String sql)
|
||||
throws SQLException {
|
||||
check(sql);
|
||||
sql = check(sql);
|
||||
return chain.connection_prepareCall(connection, sql);
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean {
|
||||
public CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection, String sql,
|
||||
int resultSetType, int resultSetConcurrency)
|
||||
throws SQLException {
|
||||
check(sql);
|
||||
sql = check(sql);
|
||||
return chain.connection_prepareCall(connection, sql, resultSetType, resultSetConcurrency);
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean {
|
||||
public CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection, String sql,
|
||||
int resultSetType, int resultSetConcurrency,
|
||||
int resultSetHoldability) throws SQLException {
|
||||
check(sql);
|
||||
sql = check(sql);
|
||||
return chain.connection_prepareCall(connection, sql, resultSetType, resultSetConcurrency, resultSetHoldability);
|
||||
}
|
||||
|
||||
@@ -229,67 +229,68 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean {
|
||||
|
||||
@Override
|
||||
public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql) throws SQLException {
|
||||
check(sql);
|
||||
sql = check(sql);
|
||||
return chain.statement_execute(statement, sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, int autoGeneratedKeys)
|
||||
throws SQLException {
|
||||
check(sql);
|
||||
sql = check(sql);
|
||||
return chain.statement_execute(statement, sql, autoGeneratedKeys);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, int columnIndexes[])
|
||||
throws SQLException {
|
||||
check(sql);
|
||||
sql = check(sql);
|
||||
return chain.statement_execute(statement, sql, columnIndexes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, String columnNames[])
|
||||
throws SQLException {
|
||||
check(sql);
|
||||
sql = check(sql);
|
||||
return chain.statement_execute(statement, sql, columnNames);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultSetProxy statement_executeQuery(FilterChain chain, StatementProxy statement, String sql)
|
||||
throws SQLException {
|
||||
check(sql);
|
||||
sql = check(sql);
|
||||
return chain.statement_executeQuery(statement, sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql) throws SQLException {
|
||||
check(sql);
|
||||
sql = check(sql);
|
||||
return chain.statement_executeUpdate(statement, sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql, int autoGeneratedKeys)
|
||||
throws SQLException {
|
||||
check(sql);
|
||||
sql = check(sql);
|
||||
return chain.statement_executeUpdate(statement, sql, autoGeneratedKeys);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql, int columnIndexes[])
|
||||
throws SQLException {
|
||||
check(sql);
|
||||
sql = check(sql);
|
||||
return chain.statement_executeUpdate(statement, sql, columnIndexes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql, String columnNames[])
|
||||
throws SQLException {
|
||||
check(sql);
|
||||
sql = check(sql);
|
||||
return chain.statement_executeUpdate(statement, sql, columnNames);
|
||||
}
|
||||
|
||||
public void check(String sql) throws SQLException {
|
||||
List<Violation> violations = provider.check(sql);
|
||||
public String check(String sql) throws SQLException {
|
||||
WallCheckResult checkResult = provider.check(sql);
|
||||
List<Violation> violations = checkResult.getViolations();
|
||||
|
||||
if (violations.size() > 0) {
|
||||
if (isLogViolation()) {
|
||||
@@ -305,6 +306,8 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return sql;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -36,5 +36,5 @@ public interface WallFilterMBean {
|
||||
|
||||
Set<String> getProviderWhiteList();
|
||||
|
||||
void check(String sql) throws SQLException;
|
||||
String check(String sql) throws SQLException;
|
||||
}
|
||||
|
||||
@@ -16,11 +16,8 @@
|
||||
package com.alibaba.druid.wall;
|
||||
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
@@ -112,22 +109,24 @@ public abstract class WallProvider {
|
||||
public abstract SQLStatementParser createParser(String sql);
|
||||
|
||||
public abstract WallVisitor createWallVisitor();
|
||||
|
||||
|
||||
public abstract ExportParameterVisitor createExportParameterVisitor();
|
||||
|
||||
public boolean checkValid(String sql) {
|
||||
return check(sql).size() == 0;
|
||||
return check(sql).getViolations().isEmpty();
|
||||
}
|
||||
|
||||
public List<Violation> check(String sql) {
|
||||
public WallCheckResult check(String sql) {
|
||||
WallCheckResult result = new WallCheckResult();
|
||||
|
||||
if (config.isAllowDoPrivileged() && privileged.get() == Boolean.TRUE) {
|
||||
return Collections.emptyList();
|
||||
return result;
|
||||
}
|
||||
|
||||
// first step, check whiteList
|
||||
boolean isWhite = whiteContains(sql);
|
||||
if (isWhite) {
|
||||
return Collections.emptyList();
|
||||
return result;
|
||||
}
|
||||
|
||||
SQLStatementParser parser = createParser(sql);
|
||||
@@ -136,34 +135,36 @@ public abstract class WallProvider {
|
||||
parser.getLexer().setAllowComment(false); // permit comment
|
||||
}
|
||||
|
||||
List<SQLStatement> statementList = new ArrayList<SQLStatement>();
|
||||
|
||||
try {
|
||||
parser.parseStatementList(statementList);
|
||||
parser.parseStatementList(result.getStatementList());
|
||||
} catch (Exception e) {
|
||||
return Collections.<Violation> singletonList(new SyntaxErrorViolation(e, sql));
|
||||
result.getViolations().add(new SyntaxErrorViolation(e, sql));
|
||||
return result;
|
||||
}
|
||||
|
||||
if (parser.getLexer().token() != Token.EOF) {
|
||||
return Collections.<Violation> singletonList(new IllegalSQLObjectViolation(sql));
|
||||
}
|
||||
|
||||
if (statementList.size() == 0) {
|
||||
return Collections.emptyList();
|
||||
result.getViolations().add(new IllegalSQLObjectViolation(sql));
|
||||
return result;
|
||||
}
|
||||
|
||||
if (statementList.size() > 1 && !config.isMultiStatementAllow()) {
|
||||
return Collections.<Violation> singletonList(new IllegalSQLObjectViolation(sql));
|
||||
if (result.getStatementList().size() == 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
SQLStatement stmt = statementList.get(0);
|
||||
if (result.getStatementList().size() > 1 && !config.isMultiStatementAllow()) {
|
||||
result.getViolations().add(new IllegalSQLObjectViolation(sql));
|
||||
return result;
|
||||
}
|
||||
|
||||
SQLStatement stmt = result.getStatementList().get(0);
|
||||
|
||||
WallVisitor visitor = createWallVisitor();
|
||||
|
||||
try {
|
||||
stmt.accept(visitor);
|
||||
} catch (ParserException e) {
|
||||
return Collections.<Violation> singletonList(new IllegalSQLObjectViolation(sql));
|
||||
result.getViolations().add(new IllegalSQLObjectViolation(sql));
|
||||
return result;
|
||||
}
|
||||
|
||||
if (visitor.getViolations().size() == 0) {
|
||||
@@ -172,7 +173,8 @@ public abstract class WallProvider {
|
||||
}
|
||||
}
|
||||
|
||||
return visitor.getViolations();
|
||||
result.getViolations().addAll(visitor.getViolations());
|
||||
return result;
|
||||
}
|
||||
|
||||
public static <T> T doPrivileged(PrivilegedAction<T> action) {
|
||||
@@ -183,4 +185,14 @@ public abstract class WallProvider {
|
||||
privileged.set(null);
|
||||
}
|
||||
}
|
||||
|
||||
private static final ThreadLocal<Object> guardValueLocal = new ThreadLocal<Object>();
|
||||
|
||||
public static void setGuardValue(Object value) {
|
||||
guardValueLocal.set(value);
|
||||
}
|
||||
|
||||
public static Object getGuardValue() {
|
||||
return guardValueLocal;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user