diff --git a/src/main/java/com/alibaba/druid/wall/WallConfig.java b/src/main/java/com/alibaba/druid/wall/WallConfig.java index 3cfb2f23b1..630bed9b3a 100644 --- a/src/main/java/com/alibaba/druid/wall/WallConfig.java +++ b/src/main/java/com/alibaba/druid/wall/WallConfig.java @@ -17,69 +17,69 @@ package com.alibaba.druid.wall; import static com.alibaba.druid.wall.spi.WallVisitorUtils.loadResource; -import java.util.HashSet; import java.util.Set; +import java.util.concurrent.ConcurrentSkipListSet; import com.alibaba.druid.wall.spi.WallVisitorUtils; public class WallConfig implements WallConfigMBean { - private boolean noneBaseStatementAllow = false; + private boolean noneBaseStatementAllow = false; - private boolean callAllow = true; - private boolean selelctAllow = true; - private boolean selectIntoAllow = true; - private boolean selectIntoOutfileAllow = false; - private boolean selectWhereAlwayTrueCheck = true; - private boolean selectHavingAlwayTrueCheck = true; - private boolean selectUnionCheck = true; + private boolean callAllow = true; + private boolean selelctAllow = true; + private boolean selectIntoAllow = true; + private boolean selectIntoOutfileAllow = false; + private boolean selectWhereAlwayTrueCheck = true; + private boolean selectHavingAlwayTrueCheck = true; + private boolean selectUnionCheck = true; - private boolean selectAllColumnAllow = true; + private boolean selectAllColumnAllow = true; - private boolean deleteAllow = true; - private boolean deleteWhereAlwayTrueCheck = true; + private boolean deleteAllow = true; + private boolean deleteWhereAlwayTrueCheck = true; - private boolean updateAllow = true; - private boolean updateWhereAlayTrueCheck = true; + private boolean updateAllow = true; + private boolean updateWhereAlayTrueCheck = true; - private boolean insertAllow = true; - private boolean mergeAllow = true; + private boolean insertAllow = true; + private boolean mergeAllow = true; - private boolean multiStatementAllow = false; + private boolean multiStatementAllow = false; - private boolean truncateAllow = false; + private boolean truncateAllow = false; - private boolean commentAllow = false; + private boolean commentAllow = false; - private boolean describeAllow = false; + private boolean describeAllow = false; - private boolean schemaCheck = true; - private boolean tableCheck = true; - private boolean functionCheck = true; - private boolean objectCheck = true; - private boolean variantCheck = true; + private boolean schemaCheck = true; + private boolean tableCheck = true; + private boolean functionCheck = true; + private boolean objectCheck = true; + private boolean variantCheck = true; - private boolean mustParameterized = false; + private boolean mustParameterized = false; - private boolean doPrivilegedAllow = false; + private boolean doPrivilegedAllow = false; - protected final Set permitFunctions = new HashSet(); - protected final Set permitTables = new HashSet(); - protected final Set permitSchemas = new HashSet(); - protected final Set permitVariants = new HashSet(); - protected final Set permitObjects = new HashSet(); + protected final Set denyFunctions = new ConcurrentSkipListSet(); + protected final Set denyTables = new ConcurrentSkipListSet(); + protected final Set denySchemas = new ConcurrentSkipListSet(); + protected final Set denyVariants = new ConcurrentSkipListSet(); + protected final Set denyObjects = new ConcurrentSkipListSet(); - protected final Set readOnlyTables = new HashSet(); + protected final Set readOnlyTables = new ConcurrentSkipListSet(); - private String dir; + private String dir; - private boolean inited; + private boolean inited; - private String tenantTablePattern; - private String tenantColumn; + private String tenantTablePattern; + private String tenantColumn; - private boolean wrapAllow = true; - private boolean metadataAllow = true; + private boolean wrapAllow = true; + private boolean metadataAllow = true; public WallConfig(){ @@ -159,11 +159,11 @@ public class WallConfig implements WallConfigMBean { dir = dir.substring(0, dir.length() - 1); } - loadResource(this.permitVariants, dir + "/permit-variant.txt"); - loadResource(this.permitSchemas, dir + "/permit-schema.txt"); - loadResource(this.permitFunctions, dir + "/permit-function.txt"); - loadResource(this.permitTables, dir + "/permit-table.txt"); - loadResource(this.permitObjects, dir + "/permit-object.txt"); + loadResource(this.denyVariants, dir + "/deny-variant.txt"); + loadResource(this.denySchemas, dir + "/deny-schema.txt"); + loadResource(this.denyFunctions, dir + "/deny-function.txt"); + loadResource(this.denyTables, dir + "/deny-table.txt"); + loadResource(this.denyObjects, dir + "/deny-object.txt"); loadResource(this.readOnlyTables, dir + "/readonly-table.txt"); } @@ -357,30 +357,38 @@ public class WallConfig implements WallConfigMBean { this.commentAllow = commentAllow; } - public Set getPermitFunctions() { - return permitFunctions; + public Set getDenyFunctions() { + return denyFunctions; } - public Set getPermitTables() { - return permitTables; + public Set getDenyTables() { + return denyTables; } - public Set getPermitSchemas() { - return permitSchemas; + public Set getDenySchemas() { + return denySchemas; } - public Set getPermitVariants() { - return permitVariants; + public Set getDenyVariants() { + return denyVariants; } - public Set getPermitObjects() { - return permitObjects; + public Set getDenyObjects() { + return denyObjects; } public Set getReadOnlyTables() { return readOnlyTables; } + public void addReadOnlyTable(String tableName) { + this.readOnlyTables.add(tableName); + } + + public boolean isReadOnly(String tableName) { + return this.readOnlyTables.contains(tableName); + } + public boolean isMustParameterized() { return mustParameterized; } @@ -389,31 +397,31 @@ public class WallConfig implements WallConfigMBean { this.mustParameterized = mustParameterized; } - public boolean isPermitObjects(String name) { + public boolean isDenyObjects(String name) { if (!objectCheck) { return false; } name = WallVisitorUtils.form(name); - return permitObjects.contains(name); + return denyObjects.contains(name); } - public boolean isPermitSchema(String name) { + public boolean isDenySchema(String name) { if (!schemaCheck) { return false; } name = WallVisitorUtils.form(name); - return this.permitSchemas.contains(name); + return this.denySchemas.contains(name); } - public boolean isPermitFunction(String name) { + public boolean isDenyFunction(String name) { if (!functionCheck) { return false; } name = WallVisitorUtils.form(name); - return this.permitFunctions.contains(name); + return this.denyFunctions.contains(name); } public boolean isCallAllow() { diff --git a/src/main/java/com/alibaba/druid/wall/WallConfigMBean.java b/src/main/java/com/alibaba/druid/wall/WallConfigMBean.java index 317f59ea18..108eee17ac 100644 --- a/src/main/java/com/alibaba/druid/wall/WallConfigMBean.java +++ b/src/main/java/com/alibaba/druid/wall/WallConfigMBean.java @@ -113,22 +113,22 @@ public interface WallConfigMBean { void setCommentAllow(boolean commentAllow); - Set getPermitFunctions(); + Set getDenyFunctions(); - Set getPermitTables(); + Set getDenyTables(); - Set getPermitSchemas(); + Set getDenySchemas(); - Set getPermitVariants(); + Set getDenyVariants(); - Set getPermitObjects(); + Set getDenyObjects(); Set getReadOnlyTables(); - boolean isPermitObjects(String name); + boolean isDenyObjects(String name); - boolean isPermitSchema(String name); + boolean isDenySchema(String name); - boolean isPermitFunction(String name); + boolean isDenyFunction(String name); } diff --git a/src/main/java/com/alibaba/druid/wall/WallContext.java b/src/main/java/com/alibaba/druid/wall/WallContext.java new file mode 100644 index 0000000000..96997cac14 --- /dev/null +++ b/src/main/java/com/alibaba/druid/wall/WallContext.java @@ -0,0 +1,34 @@ +package com.alibaba.druid.wall; + +public class WallContext { + + private final static ThreadLocal contextLocal = new ThreadLocal(); + + private WallSqlStat sqlState; + + public static WallContext createIfNotExists() { + WallContext context = contextLocal.get(); + if (context == null) { + context = new WallContext(); + contextLocal.set(context); + } + return context; + } + + public static WallContext current() { + return contextLocal.get(); + } + + public static void clearContext() { + contextLocal.remove(); + } + + public WallSqlStat getSqlState() { + return sqlState; + } + + public void setSqlState(WallSqlStat sqlState) { + this.sqlState = sqlState; + } + +} diff --git a/src/main/java/com/alibaba/druid/wall/WallDenyStat.java b/src/main/java/com/alibaba/druid/wall/WallDenyStat.java new file mode 100644 index 0000000000..9e794bde49 --- /dev/null +++ b/src/main/java/com/alibaba/druid/wall/WallDenyStat.java @@ -0,0 +1,46 @@ +package com.alibaba.druid.wall; + +import java.util.Date; +import java.util.concurrent.atomic.AtomicLongFieldUpdater; + +public class WallDenyStat { + + private volatile long denyCount; + + private volatile long lastDenyTimeMillis; + + private volatile long resetCount; + + final static AtomicLongFieldUpdater denyCountUpdater = AtomicLongFieldUpdater.newUpdater(WallDenyStat.class, + "denyCount"); + + final static AtomicLongFieldUpdater resetCountUpdater = AtomicLongFieldUpdater.newUpdater(WallDenyStat.class, + "resetCount"); + + public long incrementAndGetDenyCount() { + lastDenyTimeMillis = System.currentTimeMillis(); + return denyCountUpdater.incrementAndGet(this); + } + + public long getDenyCount() { + return denyCount; + } + + public Date getLastDenyTime() { + if (lastDenyTimeMillis <= 0) { + return null; + } + return new Date(lastDenyTimeMillis); + } + + public void reset() { + lastDenyTimeMillis = 0; + denyCount = 0; + resetCountUpdater.incrementAndGet(this); + } + + public long getResetCount() { + return this.resetCount; + } + +} diff --git a/src/main/java/com/alibaba/druid/wall/WallFilter.java b/src/main/java/com/alibaba/druid/wall/WallFilter.java index 105fe339a0..826b565b06 100644 --- a/src/main/java/com/alibaba/druid/wall/WallFilter.java +++ b/src/main/java/com/alibaba/druid/wall/WallFilter.java @@ -37,7 +37,7 @@ import com.alibaba.druid.support.logging.LogFactory; import com.alibaba.druid.util.JdbcUtils; import com.alibaba.druid.wall.spi.MySqlWallProvider; import com.alibaba.druid.wall.spi.OracleWallProvider; -import com.alibaba.druid.wall.spi.SQLServerProvider; +import com.alibaba.druid.wall.spi.SQLServerWallProvider; import com.alibaba.druid.wall.violation.SyntaxErrorViolation; public class WallFilter extends FilterAdapter implements WallFilterMBean { @@ -86,10 +86,10 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean { provider = new OracleWallProvider(config); } else if (JdbcUtils.SQL_SERVER.equals(dbType) || JdbcUtils.JTDS.equals(dbType)) { if (config == null) { - config = new WallConfig(SQLServerProvider.DEFAULT_CONFIG_DIR); + config = new WallConfig(SQLServerWallProvider.DEFAULT_CONFIG_DIR); } - provider = new SQLServerProvider(config); + provider = new SQLServerWallProvider(config); } else { throw new IllegalStateException("dbType not support : " + dbType + ", url " + dataSource.getUrl()); } @@ -159,139 +159,235 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean { @Override public void statement_addBatch(FilterChain chain, StatementProxy statement, String sql) throws SQLException { - sql = check(sql); - chain.statement_addBatch(statement, sql); + WallContext.createIfNotExists(); + try { + sql = check(sql); + chain.statement_addBatch(statement, sql); + } finally { + WallContext.clearContext(); + } } @Override public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql) throws SQLException { - sql = check(sql); - return chain.connection_prepareStatement(connection, sql); + WallContext.createIfNotExists(); + try { + sql = check(sql); + return chain.connection_prepareStatement(connection, sql); + } finally { + WallContext.clearContext(); + } } @Override public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql, int autoGeneratedKeys) throws SQLException { - sql = check(sql); - return chain.connection_prepareStatement(connection, sql, autoGeneratedKeys); + WallContext.createIfNotExists(); + try { + sql = check(sql); + return chain.connection_prepareStatement(connection, sql, autoGeneratedKeys); + } finally { + WallContext.clearContext(); + } } @Override public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql, int resultSetType, int resultSetConcurrency) throws SQLException { - sql = check(sql); - return chain.connection_prepareStatement(connection, sql, resultSetType, resultSetConcurrency); + WallContext.createIfNotExists(); + try { + sql = check(sql); + return chain.connection_prepareStatement(connection, sql, resultSetType, resultSetConcurrency); + } finally { + WallContext.clearContext(); + } } @Override public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - sql = check(sql); - return chain.connection_prepareStatement(connection, sql, resultSetType, resultSetConcurrency, - resultSetHoldability); + WallContext.createIfNotExists(); + try { + sql = check(sql); + return chain.connection_prepareStatement(connection, sql, resultSetType, resultSetConcurrency, + resultSetHoldability); + } finally { + WallContext.clearContext(); + } } @Override public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql, int[] columnIndexes) throws SQLException { - sql = check(sql); - return chain.connection_prepareStatement(connection, sql, columnIndexes); + WallContext.createIfNotExists(); + try { + sql = check(sql); + return chain.connection_prepareStatement(connection, sql, columnIndexes); + } finally { + WallContext.clearContext(); + } } @Override public PreparedStatementProxy connection_prepareStatement(FilterChain chain, ConnectionProxy connection, String sql, String[] columnNames) throws SQLException { - sql = check(sql); - return chain.connection_prepareStatement(connection, sql, columnNames); + WallContext.createIfNotExists(); + try { + sql = check(sql); + return chain.connection_prepareStatement(connection, sql, columnNames); + } finally { + WallContext.clearContext(); + } } @Override public CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection, String sql) throws SQLException { - sql = check(sql); - return chain.connection_prepareCall(connection, sql); + WallContext.createIfNotExists(); + try { + sql = check(sql); + return chain.connection_prepareCall(connection, sql); + } finally { + WallContext.clearContext(); + } } @Override public CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection, String sql, int resultSetType, int resultSetConcurrency) throws SQLException { - sql = check(sql); - return chain.connection_prepareCall(connection, sql, resultSetType, resultSetConcurrency); + WallContext.createIfNotExists(); + try { + sql = check(sql); + return chain.connection_prepareCall(connection, sql, resultSetType, resultSetConcurrency); + } finally { + WallContext.clearContext(); + } } @Override public CallableStatementProxy connection_prepareCall(FilterChain chain, ConnectionProxy connection, String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - sql = check(sql); - return chain.connection_prepareCall(connection, sql, resultSetType, resultSetConcurrency, resultSetHoldability); + WallContext.createIfNotExists(); + try { + sql = check(sql); + return chain.connection_prepareCall(connection, sql, resultSetType, resultSetConcurrency, + resultSetHoldability); + } finally { + WallContext.clearContext(); + } } // ////////////// @Override public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql) throws SQLException { - sql = check(sql); - return chain.statement_execute(statement, sql); + WallContext.createIfNotExists(); + try { + sql = check(sql); + return chain.statement_execute(statement, sql); + } finally { + WallContext.clearContext(); + } } @Override public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, int autoGeneratedKeys) throws SQLException { - sql = check(sql); - return chain.statement_execute(statement, sql, autoGeneratedKeys); + WallContext.createIfNotExists(); + try { + sql = check(sql); + return chain.statement_execute(statement, sql, autoGeneratedKeys); + } finally { + WallContext.clearContext(); + } } @Override public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, int columnIndexes[]) throws SQLException { - sql = check(sql); - return chain.statement_execute(statement, sql, columnIndexes); + WallContext.createIfNotExists(); + try { + sql = check(sql); + return chain.statement_execute(statement, sql, columnIndexes); + } finally { + WallContext.clearContext(); + } } @Override public boolean statement_execute(FilterChain chain, StatementProxy statement, String sql, String columnNames[]) throws SQLException { - sql = check(sql); - return chain.statement_execute(statement, sql, columnNames); + WallContext.createIfNotExists(); + try { + sql = check(sql); + return chain.statement_execute(statement, sql, columnNames); + } finally { + WallContext.clearContext(); + } } @Override public ResultSetProxy statement_executeQuery(FilterChain chain, StatementProxy statement, String sql) throws SQLException { - sql = check(sql); - return chain.statement_executeQuery(statement, sql); + WallContext.createIfNotExists(); + try { + sql = check(sql); + return chain.statement_executeQuery(statement, sql); + } finally { + WallContext.clearContext(); + } } @Override public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql) throws SQLException { - sql = check(sql); - return chain.statement_executeUpdate(statement, sql); + WallContext.createIfNotExists(); + try { + sql = check(sql); + return chain.statement_executeUpdate(statement, sql); + } finally { + WallContext.clearContext(); + } } @Override public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql, int autoGeneratedKeys) throws SQLException { - sql = check(sql); - return chain.statement_executeUpdate(statement, sql, autoGeneratedKeys); + WallContext.createIfNotExists(); + try { + sql = check(sql); + return chain.statement_executeUpdate(statement, sql, autoGeneratedKeys); + } finally { + WallContext.clearContext(); + } } @Override public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql, int columnIndexes[]) throws SQLException { - sql = check(sql); - return chain.statement_executeUpdate(statement, sql, columnIndexes); + WallContext.createIfNotExists(); + try { + sql = check(sql); + return chain.statement_executeUpdate(statement, sql, columnIndexes); + } finally { + WallContext.clearContext(); + } } @Override public int statement_executeUpdate(FilterChain chain, StatementProxy statement, String sql, String columnNames[]) throws SQLException { - sql = check(sql); - return chain.statement_executeUpdate(statement, sql, columnNames); + WallContext.createIfNotExists(); + try { + sql = check(sql); + return chain.statement_executeUpdate(statement, sql, columnNames); + } finally { + WallContext.clearContext(); + } } public String check(String sql) throws SQLException { @@ -355,7 +451,7 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean { if (isLogViolation()) { LOG.error("not support method : Connection.getMetdataData"); } - + if (throwException) { throw new WallSQLException("not support method : Connection.getMetdataData"); } else { @@ -369,4 +465,16 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean { public long getViolationCount() { return this.violationCount.get(); } + + public void resetViolationCount() { + this.violationCount.set(0); + } + + public void clearWhiteList() { + this.provider.clearCache(); + } + + public boolean checkValid(String sql) { + return provider.checkValid(sql); + } } diff --git a/src/main/java/com/alibaba/druid/wall/WallFilterMBean.java b/src/main/java/com/alibaba/druid/wall/WallFilterMBean.java index 297c12f336..bd2f51450c 100644 --- a/src/main/java/com/alibaba/druid/wall/WallFilterMBean.java +++ b/src/main/java/com/alibaba/druid/wall/WallFilterMBean.java @@ -39,4 +39,10 @@ public interface WallFilterMBean { String check(String sql) throws SQLException; long getViolationCount(); + + void resetViolationCount(); + + void clearWhiteList(); + + boolean checkValid(String sql); } diff --git a/src/main/java/com/alibaba/druid/wall/WallProvider.java b/src/main/java/com/alibaba/druid/wall/WallProvider.java index 92a15f36b6..fdd83c6544 100644 --- a/src/main/java/com/alibaba/druid/wall/WallProvider.java +++ b/src/main/java/com/alibaba/druid/wall/WallProvider.java @@ -19,33 +19,40 @@ import java.security.PrivilegedAction; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; import java.util.concurrent.locks.ReentrantReadWriteLock; import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.parser.NotAllowCommentException; import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.parser.SQLStatementParser; import com.alibaba.druid.sql.parser.Token; import com.alibaba.druid.sql.visitor.ExportParameterVisitor; import com.alibaba.druid.util.LRUCache; +import com.alibaba.druid.wall.spi.WallVisitorUtils; import com.alibaba.druid.wall.violation.IllegalSQLObjectViolation; import com.alibaba.druid.wall.violation.SyntaxErrorViolation; public abstract class WallProvider { - // Dummy value to associate with an Object in the backing Map - private static final Object PRESENT = new Object(); + private LinkedHashMap whiteList; - private LinkedHashMap whiteList; + private int whileListMaxSize = 1024; - private int whileListMaxSize = 1024; + private int whiteSqlMaxLength = 1024; // 1k - private int whiteSqlMaxLength = 1024; // 1k + protected final WallConfig config; - protected final WallConfig config; + private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); - private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + private static final ThreadLocal privileged = new ThreadLocal(); - private static final ThreadLocal privileged = new ThreadLocal(); + private final ConcurrentMap deniedTables = new ConcurrentHashMap(); + private final ConcurrentMap deniedFunctions = new ConcurrentHashMap(); + private final ConcurrentMap deniedSchemas = new ConcurrentHashMap(); + + public final WallDenyStat commentDeniedStat = new WallDenyStat(); public WallProvider(WallConfig config){ this.config = config; @@ -59,10 +66,10 @@ public abstract class WallProvider { lock.writeLock().lock(); try { if (whiteList == null) { - whiteList = new LRUCache(whileListMaxSize); + whiteList = new LRUCache(whileListMaxSize); } - whiteList.put(sql, PRESENT); + whiteList.put(sql, new WallSqlStat()); } finally { lock.writeLock().unlock(); } @@ -83,6 +90,10 @@ public abstract class WallProvider { } public void clearCache() { + clearWhiteList(); + } + + public void clearWhiteList() { lock.writeLock().lock(); try { if (whiteList != null) { @@ -93,19 +104,23 @@ public abstract class WallProvider { } } - public boolean whiteContains(String sql) { + public WallSqlStat getWhiteSql(String sql) { lock.readLock().lock(); try { if (whiteList == null) { - return false; + return null; } - return whiteList.get(sql) != null; + return whiteList.get(sql); } finally { lock.readLock().unlock(); } } + public boolean whiteContains(String sql) { + return getWhiteSql(sql) != null; + } + public abstract SQLStatementParser createParser(String sql); public abstract WallVisitor createWallVisitor(); @@ -113,7 +128,110 @@ public abstract class WallProvider { public abstract ExportParameterVisitor createExportParameterVisitor(); public boolean checkValid(String sql) { - return check(sql).getViolations().isEmpty(); + WallCheckResult result = check(sql); + return result.getViolations().isEmpty(); + } + + public void incrementCommentDeniedCount() { + this.commentDeniedStat.incrementAndGetDenyCount(); + } + + public boolean checkDenyFunction(String functionName) { + if (functionName == null) { + return true; + } + + functionName = functionName.toLowerCase(); + if (getConfig().getDenyFunctions().contains(functionName)) { + WallDenyStat denyStat = this.deniedFunctions.get(functionName); + if (denyStat == null) { + this.deniedFunctions.putIfAbsent(functionName, new WallDenyStat()); + denyStat = this.deniedFunctions.get(functionName); + } + denyStat.incrementAndGetDenyCount(); + return false; + } + + return true; + } + + public boolean checkDenySchema(String schemaName) { + if (schemaName == null) { + return true; + } + + schemaName = schemaName.toLowerCase(); + if (getConfig().getDenySchemas().contains(schemaName)) { + WallDenyStat denyStat = this.deniedSchemas.get(schemaName); + if (denyStat == null) { + this.deniedSchemas.putIfAbsent(schemaName, new WallDenyStat()); + denyStat = this.deniedSchemas.get(schemaName); + } + denyStat.incrementAndGetDenyCount(); + return false; + } + + return true; + } + + public boolean checkDenyTable(String tableName) { + if (tableName == null) { + return true; + } + + tableName = WallVisitorUtils.form(tableName); + if (getConfig().getDenyTables().contains(tableName)) { + WallDenyStat denyStat = this.deniedTables.get(tableName); + if (denyStat == null) { + this.deniedTables.putIfAbsent(tableName, new WallDenyStat()); + denyStat = this.deniedTables.get(tableName); + } + denyStat.incrementAndGetDenyCount(); + return false; + } + + return true; + } + + public boolean checkReadOnlyTable(String tableName) { + if (tableName == null) { + return true; + } + + tableName = WallVisitorUtils.form(tableName); + if (getConfig().isReadOnly(tableName)) { + WallDenyStat denyStat = this.deniedTables.get(tableName); + if (denyStat == null) { + this.deniedTables.putIfAbsent(tableName, new WallDenyStat()); + denyStat = this.deniedTables.get(tableName); + } + denyStat.incrementAndGetDenyCount(); + return false; + } + + return true; + } + + public WallDenyStat getDenniedTableStat(String tableName) { + if (tableName == null) { + return null; + } + + String formName = WallVisitorUtils.form(tableName); + return deniedTables.get(formName); + } + + public WallDenyStat getDenniedSchemaStat(String schemaName) { + if (schemaName == null) { + return null; + } + + String formName = WallVisitorUtils.form(schemaName); + return deniedSchemas.get(formName); + } + + public WallDenyStat getCommentDenyStat() { + return this.commentDeniedStat; } public WallCheckResult check(String sql) { @@ -124,19 +242,24 @@ public abstract class WallProvider { } // first step, check whiteList - boolean isWhite = whiteContains(sql); - if (isWhite) { + WallSqlStat sqlStat = getWhiteSql(sql); + if (sqlStat != null) { + sqlStat.incrementAndGetExecuteCount(); return result; } SQLStatementParser parser = createParser(sql); if (!config.isCommentAllow()) { - parser.getLexer().setAllowComment(false); // permit comment + parser.getLexer().setAllowComment(false); // deny comment } try { parser.parseStatementList(result.getStatementList()); + } catch (NotAllowCommentException e) { + result.getViolations().add(new SyntaxErrorViolation(e, sql)); + incrementCommentDeniedCount(); + return result; } catch (Exception e) { result.getViolations().add(new SyntaxErrorViolation(e, sql)); return result; @@ -176,13 +299,13 @@ public abstract class WallProvider { result.getViolations().addAll(visitor.getViolations()); return result; } - + public static boolean ispPivileged() { Boolean value = privileged.get(); if (value == null) { return false; } - + return value.booleanValue(); } diff --git a/src/main/java/com/alibaba/druid/wall/WallSqlStat.java b/src/main/java/com/alibaba/druid/wall/WallSqlStat.java new file mode 100644 index 0000000000..224a676843 --- /dev/null +++ b/src/main/java/com/alibaba/druid/wall/WallSqlStat.java @@ -0,0 +1,20 @@ +package com.alibaba.druid.wall; + +import java.util.concurrent.atomic.AtomicLongFieldUpdater; + +public class WallSqlStat { + + private volatile long executeCount; + + final static AtomicLongFieldUpdater executeCountUpdater = AtomicLongFieldUpdater.newUpdater(WallSqlStat.class, + "executeCount"); + + public long incrementAndGetExecuteCount() { + return executeCountUpdater.incrementAndGet(this); + } + + public long getExecuteCount() { + return executeCount; + } + +} diff --git a/src/main/java/com/alibaba/druid/wall/WallUtils.java b/src/main/java/com/alibaba/druid/wall/WallUtils.java index 8cb6fe560c..bce900a45e 100644 --- a/src/main/java/com/alibaba/druid/wall/WallUtils.java +++ b/src/main/java/com/alibaba/druid/wall/WallUtils.java @@ -17,7 +17,7 @@ package com.alibaba.druid.wall; import com.alibaba.druid.wall.spi.MySqlWallProvider; import com.alibaba.druid.wall.spi.OracleWallProvider; -import com.alibaba.druid.wall.spi.SQLServerProvider; +import com.alibaba.druid.wall.spi.SQLServerWallProvider; public class WallUtils { @@ -42,12 +42,12 @@ public class WallUtils { } public static boolean isValidateSqlServer(String sql) { - SQLServerProvider provider = new SQLServerProvider(); + SQLServerWallProvider provider = new SQLServerWallProvider(); return provider.checkValid(sql); } public static boolean isValidateSqlServer(String sql, WallConfig config) { - SQLServerProvider provider = new SQLServerProvider(config); + SQLServerWallProvider provider = new SQLServerWallProvider(config); return provider.checkValid(sql); } } diff --git a/src/main/java/com/alibaba/druid/wall/WallVisitor.java b/src/main/java/com/alibaba/druid/wall/WallVisitor.java index f1fccfeb24..34c852ed62 100644 --- a/src/main/java/com/alibaba/druid/wall/WallVisitor.java +++ b/src/main/java/com/alibaba/druid/wall/WallVisitor.java @@ -30,7 +30,7 @@ public interface WallVisitor extends SQLASTVisitor { void addViolation(Violation violation); - boolean isPermitTable(String name); + boolean isDenyTable(String name); String toSQL(SQLObject obj); } diff --git a/src/main/java/com/alibaba/druid/wall/spi/MySqlWallVisitor.java b/src/main/java/com/alibaba/druid/wall/spi/MySqlWallVisitor.java index 8a50af9d04..201fe6957c 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/MySqlWallVisitor.java +++ b/src/main/java/com/alibaba/druid/wall/spi/MySqlWallVisitor.java @@ -237,13 +237,12 @@ public class MySqlWallVisitor extends MySqlASTVisitorAdapter implements WallVisi } @Override - public boolean isPermitTable(String name) { + public boolean isDenyTable(String name) { if (!config.isTableCheck()) { return false; } - name = WallVisitorUtils.form(name); - return config.getPermitTables().contains(name); + return !this.provider.checkDenyTable(name); } public void preVisit(SQLObject x) { diff --git a/src/main/java/com/alibaba/druid/wall/spi/OracleWallVisitor.java b/src/main/java/com/alibaba/druid/wall/spi/OracleWallVisitor.java index 86de9d461d..879fd738c1 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/OracleWallVisitor.java +++ b/src/main/java/com/alibaba/druid/wall/spi/OracleWallVisitor.java @@ -83,7 +83,7 @@ public class OracleWallVisitor extends OracleASTVisitorAdapter implements WallVi public boolean visit(SQLIdentifierExpr x) { String name = x.getName(); name = WallVisitorUtils.form(name); - if (config.isVariantCheck() && config.getPermitVariants().contains(name)) { + if (config.isVariantCheck() && config.getDenyVariants().contains(name)) { getViolations().add(new IllegalSQLObjectViolation(toSQL(x))); } return true; @@ -112,8 +112,7 @@ public class OracleWallVisitor extends OracleASTVisitorAdapter implements WallVi } public boolean visit(OracleSelectTableReference x) { - WallVisitorUtils.check(this, x); - return true; + return WallVisitorUtils.check(this, x); } public boolean visit(SQLExprTableSource x) { @@ -158,7 +157,7 @@ public class OracleWallVisitor extends OracleASTVisitorAdapter implements WallVi } @Override - public boolean isPermitTable(String name) { + public boolean isDenyTable(String name) { if (!config.isTableCheck()) { return false; } @@ -167,7 +166,7 @@ public class OracleWallVisitor extends OracleASTVisitorAdapter implements WallVi if (name.startsWith("v$") || name.startsWith("v_$")) { return true; } - return config.getPermitTables().contains(name); + return !this.provider.checkDenyTable(name); } public void preVisit(SQLObject x) { diff --git a/src/main/java/com/alibaba/druid/wall/spi/SQLServerProvider.java b/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallProvider.java similarity index 89% rename from src/main/java/com/alibaba/druid/wall/spi/SQLServerProvider.java rename to src/main/java/com/alibaba/druid/wall/spi/SQLServerWallProvider.java index f9e2f57013..8a10a6ade8 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/SQLServerProvider.java +++ b/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallProvider.java @@ -30,18 +30,18 @@ import com.alibaba.druid.wall.WallVisitor; * @version 1.0, 2012-3-17 * @see */ -public class SQLServerProvider extends WallProvider { +public class SQLServerWallProvider extends WallProvider { public final static String DEFAULT_CONFIG_DIR = "META-INF/druid/wall/sqlserver"; /** * @param config */ - public SQLServerProvider(){ + public SQLServerWallProvider(){ this(new WallConfig(DEFAULT_CONFIG_DIR)); } - public SQLServerProvider(WallConfig config){ + public SQLServerWallProvider(WallConfig config){ super(config); } diff --git a/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallVisitor.java b/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallVisitor.java index 09fa50ee08..f38e6f4ffe 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallVisitor.java +++ b/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallVisitor.java @@ -80,13 +80,12 @@ public class SQLServerWallVisitor extends SQLServerASTVisitorAdapter implements } @Override - public boolean isPermitTable(String name) { + public boolean isDenyTable(String name) { if (!config.isTableCheck()) { return false; } - name = WallVisitorUtils.form(name); - return config.getPermitTables().contains(name); + return !this.provider.checkDenyTable(name); } @Override @@ -97,7 +96,7 @@ public class SQLServerWallVisitor extends SQLServerASTVisitorAdapter implements public boolean visit(SQLIdentifierExpr x) { String name = x.getName(); name = WallVisitorUtils.form(name); - if (config.isVariantCheck() && config.getPermitVariants().contains(name)) { + if (config.isVariantCheck() && config.getDenyVariants().contains(name)) { getViolations().add(new IllegalSQLObjectViolation(toSQL(x))); } return true; @@ -238,10 +237,10 @@ public class SQLServerWallVisitor extends SQLServerASTVisitorAdapter implements @Override public boolean visit(SQLServerObjectReferenceExpr x) { - if (x.getSchema() != null && config.isPermitSchema(x.getSchema())) { + if (x.getSchema() != null && !provider.checkDenySchema(x.getSchema())) { this.getViolations().add(new IllegalSQLObjectViolation(this.toSQL(x))); } - if (x.getDatabase() != null && config.isPermitSchema(x.getDatabase())) { + if (x.getDatabase() != null && !provider.checkDenySchema(x.getDatabase())) { this.getViolations().add(new IllegalSQLObjectViolation(this.toSQL(x))); } return true; diff --git a/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java b/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java index fc9258250d..18fd9a6764 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java @@ -69,7 +69,7 @@ import com.alibaba.druid.wall.violation.IllegalSQLObjectViolation; public class WallVisitorUtils { - private final static Log LOG = LogFactory.getLog(WallVisitorUtils.class); + private final static Log LOG = LogFactory.getLog(WallVisitorUtils.class); public static void check(WallVisitor visitor, SQLInListExpr x) { @@ -348,11 +348,9 @@ public class WallVisitorUtils { tableName = ((SQLName) tableNameExpr).getSimleName(); } - if (tableName != null) { - tableName = form(tableName); - if (visitor.getConfig().getReadOnlyTables().contains(tableName)) { - addViolation(visitor, tableSource); - } + boolean readOnlyValid = visitor.getProvider().checkReadOnlyTable(tableName); + if (!readOnlyValid) { + addViolation(visitor, tableSource); } } else if (tableSource instanceof SQLJoinTableSource) { SQLJoinTableSource join = (SQLJoinTableSource) tableSource; @@ -777,44 +775,54 @@ public class WallVisitorUtils { String methodName = x.getMethodName(); - if (visitor.getConfig().isPermitFunction(methodName.toLowerCase())) { + if (!visitor.getProvider().checkDenyFunction(methodName)) { addViolation(visitor, x); } } - private static void checkSchema(WallVisitor visitor, SQLExpr x) { + private static boolean checkSchema(WallVisitor visitor, SQLExpr x) { if (x instanceof SQLName) { String owner = ((SQLName) x).getSimleName(); owner = WallVisitorUtils.form(owner); - if (visitor.getConfig().isPermitSchema(owner)) { + if (!visitor.getProvider().checkDenySchema(owner)) { addViolation(visitor, x); + return false; } - if (visitor.getConfig().isPermitObjects(owner)) { + if (visitor.getConfig().isDenyObjects(owner)) { addViolation(visitor, x); + return false; } } // if (ownerExpr instanceof SQLPropertyExpr) { if (x instanceof SQLPropertyExpr) { - checkSchema(visitor, ((SQLPropertyExpr) x).getOwner()); + return checkSchema(visitor, ((SQLPropertyExpr) x).getOwner()); } + + return true; } - public static void check(WallVisitor visitor, SQLExprTableSource x) { + public static boolean check(WallVisitor visitor, SQLExprTableSource x) { SQLExpr expr = x.getExpr(); if (expr instanceof SQLPropertyExpr) { - checkSchema(visitor, ((SQLPropertyExpr) expr).getOwner()); + boolean checkResult = checkSchema(visitor, ((SQLPropertyExpr) expr).getOwner()); + if (!checkResult) { + return false; + } } if (expr instanceof SQLName) { String tableName = ((SQLName) expr).getSimleName(); - if (visitor.isPermitTable(tableName)) { + if (visitor.isDenyTable(tableName)) { addViolation(visitor, x); + return false; } } + + return true; } private static void addViolation(WallVisitor visitor, SQLObject x) { @@ -919,7 +927,7 @@ public class WallVisitorUtils { } } } catch (IOException e) { - LOG.error("load oracle permit tables errror", e); + LOG.error("load oracle deny tables errror", e); } } } diff --git a/src/main/resources/META-INF/druid/wall/mysql/permit-function.txt b/src/main/resources/META-INF/druid/wall/mysql/deny-function.txt similarity index 100% rename from src/main/resources/META-INF/druid/wall/mysql/permit-function.txt rename to src/main/resources/META-INF/druid/wall/mysql/deny-function.txt diff --git a/src/main/resources/META-INF/druid/wall/mysql/permit-schema.txt b/src/main/resources/META-INF/druid/wall/mysql/deny-schema.txt similarity index 100% rename from src/main/resources/META-INF/druid/wall/mysql/permit-schema.txt rename to src/main/resources/META-INF/druid/wall/mysql/deny-schema.txt diff --git a/src/main/resources/META-INF/druid/wall/oracle/permit-function.txt b/src/main/resources/META-INF/druid/wall/oracle/deny-function.txt similarity index 100% rename from src/main/resources/META-INF/druid/wall/oracle/permit-function.txt rename to src/main/resources/META-INF/druid/wall/oracle/deny-function.txt diff --git a/src/main/resources/META-INF/druid/wall/oracle/permit-object.txt b/src/main/resources/META-INF/druid/wall/oracle/deny-object.txt similarity index 100% rename from src/main/resources/META-INF/druid/wall/oracle/permit-object.txt rename to src/main/resources/META-INF/druid/wall/oracle/deny-object.txt diff --git a/src/main/resources/META-INF/druid/wall/oracle/permit-schema.txt b/src/main/resources/META-INF/druid/wall/oracle/deny-schema.txt similarity index 100% rename from src/main/resources/META-INF/druid/wall/oracle/permit-schema.txt rename to src/main/resources/META-INF/druid/wall/oracle/deny-schema.txt diff --git a/src/main/resources/META-INF/druid/wall/oracle/permit-table.txt b/src/main/resources/META-INF/druid/wall/oracle/deny-table.txt similarity index 100% rename from src/main/resources/META-INF/druid/wall/oracle/permit-table.txt rename to src/main/resources/META-INF/druid/wall/oracle/deny-table.txt diff --git a/src/main/resources/META-INF/druid/wall/oracle/permit-variant.txt b/src/main/resources/META-INF/druid/wall/oracle/deny-variant.txt similarity index 100% rename from src/main/resources/META-INF/druid/wall/oracle/permit-variant.txt rename to src/main/resources/META-INF/druid/wall/oracle/deny-variant.txt diff --git a/src/main/resources/META-INF/druid/wall/sqlserver/permit-function.txt b/src/main/resources/META-INF/druid/wall/sqlserver/deny-function.txt similarity index 100% rename from src/main/resources/META-INF/druid/wall/sqlserver/permit-function.txt rename to src/main/resources/META-INF/druid/wall/sqlserver/deny-function.txt diff --git a/src/main/resources/META-INF/druid/wall/sqlserver/permit-object.txt b/src/main/resources/META-INF/druid/wall/sqlserver/deny-object.txt similarity index 100% rename from src/main/resources/META-INF/druid/wall/sqlserver/permit-object.txt rename to src/main/resources/META-INF/druid/wall/sqlserver/deny-object.txt diff --git a/src/main/resources/META-INF/druid/wall/sqlserver/permit-schema.txt b/src/main/resources/META-INF/druid/wall/sqlserver/deny-schema.txt similarity index 100% rename from src/main/resources/META-INF/druid/wall/sqlserver/permit-schema.txt rename to src/main/resources/META-INF/druid/wall/sqlserver/deny-schema.txt diff --git a/src/main/resources/META-INF/druid/wall/sqlserver/permit-table.txt b/src/main/resources/META-INF/druid/wall/sqlserver/deny-table.txt similarity index 100% rename from src/main/resources/META-INF/druid/wall/sqlserver/permit-table.txt rename to src/main/resources/META-INF/druid/wall/sqlserver/deny-table.txt diff --git a/src/main/resources/META-INF/druid/wall/sqlserver/permit-variant.txt b/src/main/resources/META-INF/druid/wall/sqlserver/deny-variant.txt similarity index 100% rename from src/main/resources/META-INF/druid/wall/sqlserver/permit-variant.txt rename to src/main/resources/META-INF/druid/wall/sqlserver/deny-variant.txt diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/WallCommentTest.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/WallCommentTest.java new file mode 100644 index 0000000000..6c5aeafa12 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/WallCommentTest.java @@ -0,0 +1,57 @@ +/* + * 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. + */ +package com.alibaba.druid.bvt.filter.wall; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.wall.spi.MySqlWallProvider; +import com.alibaba.druid.wall.spi.OracleWallProvider; +import com.alibaba.druid.wall.spi.SQLServerWallProvider; + +/** + * @author wenshao + */ +public class WallCommentTest extends TestCase { + + public void testORACLE() throws Exception { + String sql = "SELECT F1, F2 FROM ABC --test"; + + OracleWallProvider provider = new OracleWallProvider(); + Assert.assertFalse(provider.checkValid(sql)); + + Assert.assertEquals(1, provider.getCommentDenyStat().getDenyCount()); + } + + public void testmysql() throws Exception { + String sql = "SELECT F1, F2 FROM ABC --test"; + + MySqlWallProvider provider = new MySqlWallProvider(); + Assert.assertFalse(provider.checkValid(sql)); + + Assert.assertEquals(1, provider.getCommentDenyStat().getDenyCount()); + } + + public void testsqlserver() throws Exception { + String sql = "SELECT F1, F2 FROM ABC --test"; + + SQLServerWallProvider provider = new SQLServerWallProvider(); + Assert.assertFalse(provider.checkValid(sql)); + + Assert.assertEquals(1, provider.getCommentDenyStat().getDenyCount()); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/WallDenySchemaTest.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/WallDenySchemaTest.java new file mode 100644 index 0000000000..89dc026d83 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/WallDenySchemaTest.java @@ -0,0 +1,38 @@ +/* + * 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. + */ +package com.alibaba.druid.bvt.filter.wall; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.wall.spi.OracleWallProvider; + +/** + * @author wenshao + * + */ +public class WallDenySchemaTest extends TestCase { + + public void testORACLE() throws Exception { + String sql = "SELECT F1, F2 FROM ALL_ALL_TABLES"; + + OracleWallProvider provider = new OracleWallProvider(); + Assert.assertFalse(provider.checkValid(sql)); + + Assert.assertEquals(1, provider.getDenniedTableStat("ALL_ALL_TABLES").getDenyCount()); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/WallDenyTableTest.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/WallDenyTableTest.java new file mode 100644 index 0000000000..985fd51cb8 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/WallDenyTableTest.java @@ -0,0 +1,38 @@ +/* + * 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. + */ +package com.alibaba.druid.bvt.filter.wall; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.wall.spi.OracleWallProvider; + +/** + * @author wenshao + * + */ +public class WallDenyTableTest extends TestCase { + + public void testORACLE() throws Exception { + String sql = "SELECT F1, F2 FROM SYS.ABC"; + + OracleWallProvider provider = new OracleWallProvider(); + Assert.assertFalse(provider.checkValid(sql)); + + Assert.assertEquals(1, provider.getDenniedSchemaStat("SYS").getDenyCount()); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/WallReadOnlyTest.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/WallReadOnlyTest.java index a883648ce0..e6224353f8 100644 --- a/src/test/java/com/alibaba/druid/bvt/filter/wall/WallReadOnlyTest.java +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/WallReadOnlyTest.java @@ -31,7 +31,7 @@ public class WallReadOnlyTest extends TestCase { private WallConfig config = new WallConfig(); protected void setUp() throws Exception { - config.getReadOnlyTables().add("members"); + config.addReadOnlyTable("members"); } private String sql = "SELECT F1, F2 members"; private String insert_sql = "INSERT INTO members (FID, FNAME) VALUES (?, ?)"; diff --git a/src/test/java/com/alibaba/druid/bvt/filter/wall/WallReadOnlyTest2.java b/src/test/java/com/alibaba/druid/bvt/filter/wall/WallReadOnlyTest2.java new file mode 100644 index 0000000000..7c189e049f --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/filter/wall/WallReadOnlyTest2.java @@ -0,0 +1,69 @@ +/* + * 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. + */ +package com.alibaba.druid.bvt.filter.wall; + +import junit.framework.TestCase; + +import org.junit.Assert; + +import com.alibaba.druid.wall.WallConfig; +import com.alibaba.druid.wall.spi.MySqlWallProvider; +import com.alibaba.druid.wall.spi.OracleWallProvider; + +/** + * 这个场景,检测可疑的Having条件 + * @author wenshao + * + */ +public class WallReadOnlyTest2 extends TestCase { + private WallConfig config = new WallConfig(); + + protected void setUp() throws Exception { + config.addReadOnlyTable("members"); + } + private String sql = "SELECT F1, F2 members"; + private String insert_sql = "INSERT INTO members (FID, FNAME) VALUES (?, ?)"; + private String update_sql = "UPDATE members SET FNAME = ? WHERe FID = ?"; + private String delete_sql = "DELETE members WHERE FID = ?"; + + public void testMySql() throws Exception { + MySqlWallProvider provider = new MySqlWallProvider(config); + Assert.assertTrue(provider.checkValid(sql)); + + Assert.assertNull(provider.getDenniedTableStat("members")); + + Assert.assertFalse(provider.checkValid(insert_sql)); + Assert.assertFalse(provider.checkValid(update_sql)); + Assert.assertFalse(provider.checkValid(delete_sql)); + + Assert.assertEquals(3, provider.getDenniedTableStat("members").getDenyCount()); + Assert.assertEquals(3, provider.getDenniedTableStat("Members").getDenyCount()); + } + + public void testORACLE() throws Exception { + OracleWallProvider provider = new OracleWallProvider(config); + Assert.assertTrue(provider.checkValid(sql)); + + Assert.assertNull(provider.getDenniedTableStat("members")); + + Assert.assertFalse(provider.checkValid(insert_sql)); + Assert.assertFalse(provider.checkValid(update_sql)); + Assert.assertFalse(provider.checkValid(delete_sql)); + + Assert.assertEquals(3, provider.getDenniedTableStat("members").getDenyCount()); + Assert.assertEquals(3, provider.getDenniedTableStat("Members").getDenyCount()); + } +}