我读到有关准备语句是避免sql注入数据库的好方法。 问题是客户想要一个安静的变量UI 他首先选择一个表,然后是一些由列和文本组成的约束。 所以基本上(天真的)最终产品看起来像这样:
Select * from %TABLENAME% where %ATTRIBUTENAME% = %VALUE%
现在的问题是如何确保安全?
当然,我可以构建一个prepare Statement解决方案,我提前为所有表创建语句,但这听起来像是一个非常愚蠢的想法,因为维护它的努力会很安静(客户很安静)几张桌子)。 知道如何以尽可能通用的安全方式解决这个问题吗?
答案 0 :(得分:1)
您应该将示例更改为
select * from %TABLENAME% where %ATTRIBUTENAME% = ?
这样至少VALUE
不能用于SQL注入。然后,您可以针对数据库中的已知表和列对TABLENAME
和ATTRIBUTENAME
进行验证。
请参阅运行时验证中可能使用的DatabaseMetaData.getColumns(...)。或者,您可能会使用有效的表/列保留在构建时生成的静态文件。
您可以在构建时为每个表/列组合生成Enum
吗?我知道jOOQ从db模式生成这种构建时间java代码...也许它可以帮助吗?
例如
public enum TableColumn {
CUSTOMER_NAME("customer", "name"), CUSTOMER_ID("customer", "id"),
ORDER_ID("order", "id"), // etc etc
String table;
String column;
public TableColumn(String table, String column) {
// set values
}
}
public List<Row> doSelect(TableColumn tc, Object value) {
String sql = String.format("select * from %s where %s = ?", tc.table, tc.column);
Connection con = getConnection();
try {
PreparedStatement ps = con.prepareStatement(sql);
ps.setObject(1, value);
...