使用预准备语句和变量将Java中的Order By与JDBC驱动程序绑定

我在用着

  1. jdbcTemplate与mySQL数据库建立JDBC连接
  2. 准备好的语句尽可能地保护自己免受SQL注入攻击
  3. 需要接受来自用户的请求,以对十几个不同列中的任何一列进行数据排序
  4. 以下声明

    jdbcTemplate.query("SELECT * FROM TABLE1 ORDER BY ? ?", colName, sortOrder); 

当然这不起作用,因为变量绑定不应该仅为查询中的表达式的参数值指定列名。

那么……人们如何解决这个问题呢? 只是在Java代码中进行排序似乎是一个简单的解决方案,但是因为我得到一个变量字符串供列排序,一个变量告诉我排序顺序….这是一个丑陋的比较器条件数量盖。 这似乎应该是解决它的常见模式的常见问题……

占位符? 只能用于参数值,但不能用于列和排序顺序方向。 所以标准的方法是这样指出,例如这里是使用String#format()或类似的东西将你的列名和订单值附加到你的查询。

另一种选择是使用Spring Data JPA,您可以将方法作为参数提供给Sort类型的实例,该实例可以包含要排序的数据库所需的所有信息。

我只是将列名称和顺序连接到SQL查询,但仅限于之后

  1. validation列名称和顺序在此上下文中是否有效。
  2. 清理它们以对抗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等……对于攻击者来说,这是一个很好的帮助。