做sql 列权限校验,需要知道所有查询的列,例如这个sql: select * from table1 a left outer join table2 b on a.id=b.id 会读取两个表的所有列,columns中能够加上table1.* , table2.*
原提问者GitHub用户melin
您可以使用SchemaStatVisitor来解析SQL查询语句,并保留星号(*)的信息。
SchemaStatVisitor是Druid中提供的一个访问者模式的工具,用于解析和遍历SQL语句的结构。通过扩展SchemaStatVisitor类并覆盖相应的方法,您可以在解析SQL时获取列、表等信息。
以下是一个示例代码段,展示了如何使用SchemaStatVisitor解析SQL查询语句,并保留星号(*)的信息:
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;
import com.alibaba.druid.sql.parser.SQLParserUtils;
import com.alibaba.druid.sql.parser.SQLStatementParser;
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
import com.alibaba.druid.util.JdbcConstants;
public class QueryParserExample {
public static void main(String[] args) {
String sql = "SELECT * FROM table1 a LEFT OUTER JOIN table2 b ON a.id=b.id";
SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, JdbcConstants.MYSQL);
SchemaStatVisitor visitor = new MySqlSchemaStatVisitor();
parser.parseStatementList().forEach(statement -> statement.accept(visitor));
// 获取所有表名和列名
System.out.println("Tables: " + visitor.getTables());
System.out.println("Columns: " + visitor.getColumns());
// 获取包含星号(*)的表名和列名
visitor.visit(new MySqlSchemaStatVisitor.VisitorFeature() {
@Override
public void visit(SchemaStatVisitor visitor) {
if (visitor instanceof MySqlSchemaStatVisitor) {
MySqlSchemaStatVisitor mysqlVisitor = (MySqlSchemaStatVisitor) visitor;
System.out.println("Tables with *: " + mysqlVisitor.getAliasMap());
System.out.println("Columns with *: " + mysqlVisitor.getSelectItemCounts());
}
}
});
}
}
在上述示例中,我们使用MySqlSchemaStatVisitor作为SchemaStatVisitor的实现,来解析MySQL语句。您可以根据具体的数据库类型选择相应的SchemaStatVisitor实现。
通过访问visitor的getTables()方法和getColumns()方法,您可以获取所有表名和列名的信息。而对于包含星号(*)的表名和列名,您可以使用MySqlSchemaStatVisitor的getAliasMap()方法和getSelectItemCounts()方法来获取。
请注意,这只是一个简单的示例代码,您可以根据需要进行适当的调整和扩展,以满足您的具体需求。
果您需要在SQL执行时进行列权限校验,可以在SQL中使用完整的列名,而不是使用通配符*。这样,您可以明确指定要查询的列,并进行列级别的权限校验。
对于您提到的示例SQL语句,您可以明确指定要查询的列,例如:
stylus
Copy
SELECT a.id, a.column1, a.column2, b.column1 AS b_column1, b.column2 AS b_column2
FROM table1 a
LEFT OUTER JOIN table2 b ON a.id=b.id
在这个SQL语句中,我们明确指定了要查询的列,并使用了表别名来区分不同表格的列。这样,您可以对每个列进行权限校验,而不是对整个表格进行权限校验。
如果您需要查询所有列,但仍然需要进行列级别的权限校验,您可以使用类似于您提到的通配符的方式,并带上表别名,例如:
Copy
SELECT a., b.
FROM table1 a
LEFT OUTER JOIN table2 b ON a.id=b.id
在这个SQL语句中,我们使用了通配符来查询所有列,但是同时带上了表别名,以便进行列级别的权限校验。请注意,这种方式可能会导致性能问题,因为查询结果将包含所有列,而不是仅包含必要的列。因此,建议您明确指定要查询的列,以便提高性能并进行列级别的权限校验。
更好的解决方案是在代码中进行校验,根据查询的表和列名进行验证,如果列名不在允许的范围内,就抛出异常。具体实现方式可以使用ORM框架,例如Hibernate,使用注解或者XML配置文件来限制列名。
问题已修复,请用新版本 https://github.com/alibaba/druid/releases/tag/1.1.14
原回答者GitHub用户wenshao
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。