【问题标题】:Sanitizing SQL input in Java when using LIKE使用 LIKE 时在 Java 中清理 SQL 输入
【发布时间】:2013-10-15 16:40:25
【问题描述】:

我们都知道在 Java 中应该使用 PreparedStatments 来避免安全漏洞。

但是,我注意到当使用 LIKE 语句进行“开始于”搜索时,PreparedStatments 可能会导致性能问题。因为该语句是在没有值的情况下编译的,所以驱动程序必须假定通配符可以在任何地方,包括开头,因此它会跳过该列上的任何索引。但是,如果您使用 LIKE 值作为文字来编译语句,它会看到它可以在值上使用列的索引,直到通配符和查询执行良好。

//safe, but prepared statement can't use index on MYCOL
String userInput = "myval%";
statement = conn.prepareStatement("SELECT * FROM MYTABLE WHERE MYCOL LIKE ?");
statement.setString(1, userInput);
rs = statement.executeQuery();


//can use index on MYCOL, but is not safe
statement = conn.createStatement();
rs = statement.executeQuery("SELECT * FROM MYTABLE WHERE MYCOL LIKE '"+userInput+"'");

那么如何在保留索引的同时避免安全漏洞呢?我假设我将不得不尝试清理输入而不是使用 PreparedStatement - 如果是这样,是否存在一个库来正确执行它?或者是否有相同的 java.sql 或(oracle)数据库提示方式告诉准备好的语句它将能够使用值上的索引?

【问题讨论】:

  • 为什么不提示数据库使用索引?
  • @YourCommonSense,我确实提到了提示,不是吗。好吧,如果可能的话,我宁愿不使用它们。我的查询是针对可能基于最多 6-7 个不同列的 LIKE 进行选择的搜索。我担心提示会选择错误的索引.....

标签: java sql prepared-statement indexing sql-like


【解决方案1】:

您是否考虑过在数据库端创建一个存储过程?这样,您只需将 stored_procedure 名称和类似字符串作为参数发送到数据库,并在 java 端处理结果集。这样,您就知道您的查询将使用您正在处理的表的索引。

【讨论】:

  • 在这种情况下,因为我们正在基于 6-7 个不同的列动态构建 SQL(请参阅我对问题的评论),我不确定将问题移至数据库是否能解决任何问题。也许我错过了什么。
【解决方案2】:

为此创建一个 sql 函数,或者使用第二种方法并转义字符 (' -->> '')

String userInput="IBM";
statement = conn.createStatement();
    rs = statement.executeQuery("SELECT * FROM MYTABLE WHERE MYCOL LIKE '"+userInput.replaceAll("'","''")+"%'");

【讨论】:

  • 它是这样的转义码,让您对 sql 注入攻击敞开大门......
  • 我知道。我不知道 MySQL 转义字符,但在许多系统中,注入以 ' 开头,您可以将其更改为 '',这意味着用户输入时使用单引号。
  • @user2511414,我和 jtahlborn 一起做这个。我见过的大多数攻击都以贴切的引用开头....但我不愿意冒险将我的数据作为一个全面的解决方案。
  • 我知道并同意伙计,但这至少是解决方案,正如我一开始所说,最好让一个程序为你做,然后调用程序,或者使用全文函数.
  • 我已经有一段时间没有看到这个问题了——我仍然希望得到答复。我认为,最令人沮丧的是 jtahlborn 的评论,这意味着这种特殊的方法是有缺陷的,但提供了关于原因的反馈。
猜你喜欢
  • 2020-09-09
  • 1970-01-01
  • 2016-04-29
  • 1970-01-01
  • 1970-01-01
  • 2011-02-14
  • 1970-01-01
  • 2011-01-27
  • 2018-11-04
相关资源
最近更新 更多