在 Java 中通过 JDBC 驱动程序使用准备好的语句和变量绑定 Order By

问题描述 投票:0回答:4

我正在使用

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

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

当然,这是行不通的,因为变量绑定不应该指定列名,而只是查询中表达式的参数值。

那么......人们如何解决这个问题?仅在 Java 代码中进行排序似乎是一个简单的解决方案,但由于我得到了一个用于排序的列的变量字符串,以及一个告诉我排序顺序的变量......这是一个丑陋的比较器条件数覆盖。这看起来应该是一个常见问题,有一个常见的模式来解决它......

java sorting jdbc collections jdbctemplate
4个回答
28
投票

占位符

?
只能用于参数值,但不能用于列和排序顺序方向。因此,执行此操作的标准方法如下所示: here 是使用 String#format() 或类似的东西将列名称和顺序值附加到查询中。

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


2
投票

我只是将列名和顺序连接到 SQL 查询,但仅在

之后
  1. 验证列名称和顺序在此上下文中有效。
  2. 清理它们以对抗任何“SQL 注入”攻击的尝试。
  3. 我觉得这比将结果获取到应用层并在这里排序更高效。


2
投票
安全

的解决方案。 一开始,我们以最简单的方式启动我们的地图。为了方便起见,我重载了 get (Obiect key) 方法,以在失败时返回

default

列(“fullName”)。这将防止 SqlException。 static Map<String,String> sortCol; { sortCol = new HashMap<String, String>(){ {//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 等......对于攻击者来说,这是一个很大的帮助。


0
投票

SELECT * FROM TABLE1 ORDER BY CASE ? WHEN 'col1' THEN col1 ELSE col2 END

© www.soinside.com 2019 - 2024. All rights reserved.