mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
WallFilter support postgres
This commit is contained in:
+87
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* 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.sql.dialect.postgresql.visitor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLOrderBy;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLBetweenExpr;
|
||||
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.statement.SQLSelectGroupByClause;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
|
||||
import com.alibaba.druid.sql.visitor.ExportParameterVisitor;
|
||||
import com.alibaba.druid.sql.visitor.ExportParameterVisitorUtils;
|
||||
|
||||
public class PGExportParameterVisitor extends PGASTVisitorAdapter implements ExportParameterVisitor {
|
||||
|
||||
private final List<Object> parameters;
|
||||
|
||||
public PGExportParameterVisitor() {
|
||||
this(new ArrayList<Object>());
|
||||
}
|
||||
|
||||
public PGExportParameterVisitor(List<Object> parameters){
|
||||
this.parameters = parameters;
|
||||
}
|
||||
|
||||
public List<Object> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLSelectItem x) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLOrderBy x) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLSelectGroupByClause x) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLMethodInvokeExpr x) {
|
||||
ExportParameterVisitorUtils.exportParamterAndAccept(this.parameters, x.getParameters());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLInListExpr x) {
|
||||
ExportParameterVisitorUtils.exportParamterAndAccept(this.parameters, x.getTargetList());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLBetweenExpr x) {
|
||||
ExportParameterVisitorUtils.exportParameter(this.parameters, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(SQLBinaryOpExpr x) {
|
||||
ExportParameterVisitorUtils.exportParameter(this.parameters, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -45,7 +45,7 @@ public class WallConfig implements WallConfigMBean {
|
||||
private boolean insertAllow = true;
|
||||
private boolean mergeAllow = true;
|
||||
private boolean minusAllow = false;
|
||||
private boolean intersectAllow = false;
|
||||
private boolean intersectAllow = false;
|
||||
|
||||
private boolean multiStatementAllow = false;
|
||||
|
||||
@@ -73,6 +73,10 @@ public class WallConfig implements WallConfigMBean {
|
||||
protected final Set<String> denyVariants = new ConcurrentSkipListSet<String>();
|
||||
protected final Set<String> denyObjects = new ConcurrentSkipListSet<String>();
|
||||
|
||||
protected final Set<String> permitFunctions = new ConcurrentSkipListSet<String>();
|
||||
protected final Set<String> permitTables = new ConcurrentSkipListSet<String>();
|
||||
protected final Set<String> permitSchemas = new ConcurrentSkipListSet<String>();
|
||||
|
||||
protected final Set<String> readOnlyTables = new ConcurrentSkipListSet<String>();
|
||||
|
||||
private String dir;
|
||||
@@ -91,11 +95,11 @@ public class WallConfig implements WallConfigMBean {
|
||||
public WallConfig(){
|
||||
|
||||
}
|
||||
|
||||
|
||||
public boolean isIntersectAllow() {
|
||||
return intersectAllow;
|
||||
}
|
||||
|
||||
|
||||
public void setIntersectAllow(boolean intersectAllow) {
|
||||
this.intersectAllow = intersectAllow;
|
||||
}
|
||||
@@ -204,6 +208,10 @@ public class WallConfig implements WallConfigMBean {
|
||||
loadResource(this.denyTables, dir + "/deny-table.txt");
|
||||
loadResource(this.denyObjects, dir + "/deny-object.txt");
|
||||
loadResource(this.readOnlyTables, dir + "/readonly-table.txt");
|
||||
|
||||
loadResource(this.permitFunctions, dir + "/permit-function.txt");
|
||||
loadResource(this.permitTables, dir + "/permit-table.txt");
|
||||
loadResource(this.permitSchemas, dir + "/permit-schema.txt");
|
||||
}
|
||||
|
||||
public boolean isNoneBaseStatementAllow() {
|
||||
@@ -444,6 +452,18 @@ public class WallConfig implements WallConfigMBean {
|
||||
return this.readOnlyTables.contains(tableName);
|
||||
}
|
||||
|
||||
public Set<String> getPermitFunctions() {
|
||||
return permitFunctions;
|
||||
}
|
||||
|
||||
public Set<String> getPermitTables() {
|
||||
return permitTables;
|
||||
}
|
||||
|
||||
public Set<String> getPermitSchemas() {
|
||||
return permitSchemas;
|
||||
}
|
||||
|
||||
public boolean isMustParameterized() {
|
||||
return mustParameterized;
|
||||
}
|
||||
|
||||
@@ -37,6 +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.PGWallProvider;
|
||||
import com.alibaba.druid.wall.spi.SQLServerWallProvider;
|
||||
import com.alibaba.druid.wall.violation.SyntaxErrorViolation;
|
||||
|
||||
@@ -90,6 +91,12 @@ public class WallFilter extends FilterAdapter implements WallFilterMBean {
|
||||
}
|
||||
|
||||
provider = new SQLServerWallProvider(config);
|
||||
} else if (JdbcUtils.POSTGRESQL.equals(dbType)) {
|
||||
if (config == null) {
|
||||
config = new WallConfig(PGWallProvider.DEFAULT_CONFIG_DIR);
|
||||
}
|
||||
|
||||
provider = new PGWallProvider(config);
|
||||
} else {
|
||||
throw new IllegalStateException("dbType not support : " + dbType + ", url " + dataSource.getUrl());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.wall.spi;
|
||||
|
||||
import com.alibaba.druid.sql.dialect.postgresql.parser.PGSQLStatementParser;
|
||||
import com.alibaba.druid.sql.dialect.postgresql.visitor.PGExportParameterVisitor;
|
||||
import com.alibaba.druid.sql.parser.SQLStatementParser;
|
||||
import com.alibaba.druid.sql.visitor.ExportParameterVisitor;
|
||||
import com.alibaba.druid.util.JdbcConstants;
|
||||
import com.alibaba.druid.wall.WallConfig;
|
||||
import com.alibaba.druid.wall.WallProvider;
|
||||
import com.alibaba.druid.wall.WallVisitor;
|
||||
|
||||
|
||||
public class PGWallProvider extends WallProvider {
|
||||
|
||||
public final static String DEFAULT_CONFIG_DIR = "META-INF/druid/wall/postgres";
|
||||
|
||||
public PGWallProvider(){
|
||||
this(new WallConfig(DEFAULT_CONFIG_DIR));
|
||||
}
|
||||
|
||||
public PGWallProvider(WallConfig config){
|
||||
super(config, JdbcConstants.POSTGRESQL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLStatementParser createParser(String sql) {
|
||||
return new PGSQLStatementParser(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WallVisitor createWallVisitor() {
|
||||
return new PGWallVisitor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExportParameterVisitor createExportParameterVisitor() {
|
||||
return new PGExportParameterVisitor();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
* 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.wall.spi;
|
||||
|
||||
import java.util.ArrayList;
|
||||
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.SQLDeleteStatement;
|
||||
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.visitor.PGASTVisitorAdapter;
|
||||
import com.alibaba.druid.wall.Violation;
|
||||
import com.alibaba.druid.wall.WallConfig;
|
||||
import com.alibaba.druid.wall.WallProvider;
|
||||
import com.alibaba.druid.wall.WallVisitor;
|
||||
import com.alibaba.druid.wall.violation.IllegalSQLObjectViolation;
|
||||
|
||||
public class PGWallVisitor extends PGASTVisitorAdapter implements WallVisitor {
|
||||
|
||||
private final WallConfig config;
|
||||
private final WallProvider provider;
|
||||
private final List<Violation> violations = new ArrayList<Violation>();
|
||||
|
||||
public PGWallVisitor(WallProvider provider){
|
||||
this.config = provider.getConfig();
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
public WallProvider getProvider() {
|
||||
return provider;
|
||||
}
|
||||
|
||||
public WallConfig getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public void addViolation(Violation violation) {
|
||||
this.violations.add(violation);
|
||||
}
|
||||
|
||||
public List<Violation> getViolations() {
|
||||
return violations;
|
||||
}
|
||||
|
||||
public boolean visit(SQLIdentifierExpr x) {
|
||||
String name = x.getName();
|
||||
name = WallVisitorUtils.form(name);
|
||||
if (config.isVariantCheck() && config.getDenyVariants().contains(name)) {
|
||||
getViolations().add(new IllegalSQLObjectViolation(toSQL(x)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(SQLPropertyExpr x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(SQLInListExpr x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(SQLBinaryOpExpr x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLMethodInvokeExpr x) {
|
||||
WallVisitorUtils.checkFunction(this, x);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(OracleSelectTableReference x) {
|
||||
return WallVisitorUtils.check(this, x);
|
||||
}
|
||||
|
||||
public boolean visit(SQLExprTableSource x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
|
||||
if (x.getExpr() instanceof SQLName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean visit(SQLSelectGroupByClause x) {
|
||||
WallVisitorUtils.checkHaving(this, x.getHaving());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLSelectQueryBlock x) {
|
||||
WallVisitorUtils.checkSelelct(this, x);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLUnionQuery x) {
|
||||
WallVisitorUtils.checkUnion(this, x);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toSQL(SQLObject obj) {
|
||||
return SQLUtils.toOracleString(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDenyTable(String name) {
|
||||
if (!config.isTableCheck()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
name = WallVisitorUtils.form(name);
|
||||
if (name.startsWith("v$") || name.startsWith("v_$")) {
|
||||
return true;
|
||||
}
|
||||
return !this.provider.checkDenyTable(name);
|
||||
}
|
||||
|
||||
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(toSQL(x)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLSelectStatement x) {
|
||||
if (!config.isSelelctAllow()) {
|
||||
this.getViolations().add(new IllegalSQLObjectViolation(this.toSQL(x)));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLInsertStatement x) {
|
||||
WallVisitorUtils.checkInsert(this, x);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLDeleteStatement x) {
|
||||
WallVisitorUtils.checkDelete(this, x);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLUpdateStatement x) {
|
||||
WallVisitorUtils.checkUpdate(this, x);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLSelectItem x) {
|
||||
WallVisitorUtils.check(this, x);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user