使用预准备语句和变量将Java中的Order By与JDBC驱动程序绑定
我在用着
- jdbcTemplate与mySQL数据库建立JDBC连接
- 准备好的语句尽可能地保护自己免受SQL注入攻击
- 需要接受来自用户的请求,以对十几个不同列中的任何一列进行数据排序
-
以下声明
jdbcTemplate.query("SELECT * FROM TABLE1 ORDER BY ? ?", colName, sortOrder);
当然这不起作用,因为变量绑定不应该仅为查询中的表达式的参数值指定列名。
那么……人们如何解决这个问题呢? 只是在Java代码中进行排序似乎是一个简单的解决方案,但是因为我得到一个变量字符串供列排序,一个变量告诉我排序顺序….这是一个丑陋的比较器条件数量盖。 这似乎应该是解决它的常见模式的常见问题……
占位符?
只能用于参数值,但不能用于列和排序顺序方向。 所以标准的方法是这样指出,例如这里是使用String#format()或类似的东西将你的列名和订单值附加到你的查询。
另一种选择是使用Spring Data JPA,您可以将方法作为参数提供给Sort类型的实例,该实例可以包含要排序的数据库所需的所有信息。
我只是将列名称和顺序连接到SQL查询,但仅限于之后
- validation列名称和顺序在此上下文中是否有效。
- 清理它们以对抗SQL注入攻击的任何尝试。
我觉得与将结果提取到应用程序层并在此处对它们进行排序相比,这是有效的。
我的建议是键和列的映射。 这是一个安全的解决方案。
一开始,我们以最简单的方式启动地图。 为方便起见,我重载了get(Obiect key)方法,以便在发生故障时返回默认列(“fullName”)。 这将防止SqlExeption。
static Map sortCol; { sortCol = new HashMap(){ {//Enter all data for mapping put("name","fullName"); put("rok","year"); put("rate","likes"); put("count-rate","countRate"); } /** * * @param key for column name * @return column name otherwise default "fullName" */ @Override public String get(Object key) { String col =super.get(key); return null==col?"fullName":col; } }; }
这是一个简单的使用示例。
String sqlQuery= "Select \"fullName\",year,likes,count-rate, country ..."+ "from blaBla..."+ "where blaBla..."+ "order by "+sortCol.get("keySort") "\n"; // keySort can have the value name, count-rate etc ..
顺便说一句,你永远不应该在用户界面中透露列的真实名称,例如REST或SOAP等……对于攻击者来说,这是一个很好的帮助。