【问题标题】:How can I inject "variables" WHERE clauses into a query?如何将“变量”WHERE 子句注入查询?
【发布时间】:2017-05-23 22:06:00
【问题描述】:

我有一个问题:

SELECT * FROM table_name WHERE name=? surname=? gender=?;

我必须将字符串注入查询中(我使用准备好的语句),但问题是这 3 个子句是可变的;根据用户的输入,我可以激活 0、1 或所有 3 个子句。

如果用户不为它们输入任何内容,我如何“忽略”它们?

谢谢大家!

编辑:如果有人知道如何将 setStrin() 设置为preparedStatement 而不让他将' ' 放在字符串周围,那也很好。

【问题讨论】:

  • 动态 SQL 取胜。
  • 要么准备所有七种可能的组合(如果没有子句也是一个选项,则为 8 种),或者动态构建查询。
  • 查看标准。顺便说一下,下面的解决方案正在运行。
  • 如果您可以使用setString() 允许它不在值周围加上引号,那么防止注入将毫无用处。任何人都可以拥有像true ; drop table table_name; -- 这样的值。

标签: java mysql sql where


【解决方案1】:

最简单的解决方案是动态构建准备好的语句,如下所示:

String sql = "SELECT * FROM table_name";

if (nameInput != null || surnameInput != null || genderInput != null)
{
    sql += " WHERE ";
}

if (nameInput != null)
{
    sql += "name=? ";
}

我认为您从那里得到了其他输入的想法。

然后,您可以将 sql 的最终值与输入值一起传递到您的 prepare 调用中。

【讨论】:

  • 对不起,我看到了 [mysql] 标签,并反射性地用 PHP 编写了我的答案。我希望我对 Java 的尝试是好的(至少在你可以理解的意义上)。
  • 但是这种方式是可以注射的!我想阻止它(这就是为什么我使用 prepareStatement 和 setString()
  • @ClaudioCiociola 这不是可注入的,因为您动态构建 查询框架,但您只将用户的值添加到准备好的语句中。
  • @ClaudioCiociola 它并不比你已经拥有的更可注射。
  • 这不容易受到恶意SQL注入的影响,您仍然需要准备语句,您只是在将语句发送到数据库之前在java中有条件地构建语句。小提示,当我做这样的事情时,我倾向于添加 WHERE 1 = 1 作为初始子句,这样我就知道任何进一步的谓词应该是 AND Col=? 并且不需要检查它是否是第一个谓词并且应该开始使用WHERE 而不是AND
【解决方案2】:

无需任何复杂或昂贵的逻辑,只需一行即可轻松完成...

假设您的三个变量是@name、@surname 和@gender。

还假设在不需要过滤器时将提供一个长度为零的字符串。

那么,您的 Select 语句就是:

    select * from table_name where (name = @name or @name = '') and (surname = @surname or @surname = '') and (gender = @gender or @gender = '')

这就是它的全部内容!没有复杂或昂贵的逻辑。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-16
    • 2016-08-09
    • 1970-01-01
    相关资源
    最近更新 更多