【问题标题】:Sanitizing database input in Java without PreparedStatement在没有 PreparedStatement 的情况下清理 Java 中的数据库输入
【发布时间】:2014-07-17 01:17:19
【问题描述】:

有没有一种可靠的方法可以在不使用预准备语句的情况下清理 Java 中的数据库输入?

我找到的所有答案都建议使用 PreparedStatement,但我试图避免到数据库服务器的额外往返。

-- 附加信息--

  • 我的查询将非常简单,并且很少会共享相同的格式,因此任何查询计划缓存的性能优势都很少。
  • 数据库服务器将位于单独的物理位置,但仍位于同一 LAN 中,因此使用预准备语句时需要额外的往返行程,因此会出现额外的网络瓶颈。

我希望找到这样的东西,它存在于 C、Python 和 PHP 中: http://dev.mysql.com/doc/refman/5.0/en/mysql-real-escape-string.html

【问题讨论】:

  • jpa 持久性和 DAO 怎么样?
  • 额外的往返行程实际上会导致性能问题,还是您只是假设它会?
  • @IwishIcouldthinkofagood 我不熟悉它们,我会看看。
  • @DonRoby 我只是假设它会。我正在本地开发,生产服务器尚未设置,因此无法验证。我正在执行的查询将非常简单,并且大多数情况下将无法重用之前查询中的相同查询计划。
  • 看看这个。它提到了缓存数据库和连接池的语句。如果你想要性能,准备好的语句实际上是要走的路。 theserverside.com/news/1365244/…

标签: java mysql database sanitization


【解决方案1】:

您可以在org.apache.commons.lang.StringEscapeUtils 中使用escapeSql:

username="'; or 1=1";
sane_username=StringEscapeUtils.escapeSql(username);
// turns into "''; or 1=1"

sql= "select username from users where username = '" + sane_username + "'";
// select username from users where username = '''; 1 or 1'

但这确实是一种糟糕的做法。您应该始终使用准备好的语句。

  • 节省 sql server 的内存
  • 允许您在不重新解析 sql 的情况下重用 sql 语句, 提高性能
  • 更安全,您可能会忘记注意一些输入。

【讨论】:

  • 感谢您的回答。出于性能原因,我试图避免使用准备好的语句。如果我要多次运行同一个查询计划,Prep 语句会更有效,而我目前正在编写的这个应用程序并非如此。
  • 仅供参考 @sn00k4h, escapeSql 仅提供字符串转义,不转义特殊字符,并且由于 those 原因在 apache commons 中不再可用; sabertiger 是正确的,这是不好的做法,请使用准备好的语句,因为它们是特定于数据库的,并且可以处理目标平台的所有必要转义。
  • 嗨@raffian,我希望找到类似的东西,它存在于 C、Python 和 PHP 中:dev.mysql.com/doc/refman/5.0/en/mysql-real-escape-string.html
【解决方案2】:

这听起来像是premature optimization 的经典案例。是的,PreparedStatements 做了一些不必要的工作,就像ArrayLists 分配不必要的内存一样。但是这些实用程序的好处远远超过了它们的额外成本,而且 JIT(或 JDBC 驱动程序,在 PreparedStatement 的情况下)可以随着时间的推移而改进,从而使它们变得更便宜。

另一方面,如果您手动重新发明轮子,您很可能会犯错误,并且永远处于困境中,以确保它在未来仍然保持高性能。假设您投入大量精力来构建 PreparedStatement 的安全替代方案,但在明年发现驱动程序更新实际上使 PreparedStatement 调用比您的实现更有效 - 这不是一个牵强的想法。

性能问题很重要,但要避免在应用程序的最后一次退出时陷入困境。与将大量时间投入到项目的一个小方面相比,简单地做一些可行的事情在未来可能会更快、更安全、更容易升级。换句话说,在您最终确定它会阻止您进一步提高之前,为什么要绕开PreparedStatement 提供的美妙福利?

【讨论】:

  • 我明白你在说什么。我不是要重新发明轮子。我实际上是在问这样的轮子是否已经存在:) 如果你想象你来自一个两个“轮子”分别存在的语言,这不会感觉像是过早的优化,而是仅仅为了输入卫生目的而使用准备好的语句会感觉有点矫枉过正。
  • 像mysql_real_escape_string() 这样的“轮子”的问题是它们非常脆弱,容易出现故障或错误。是的,如果使用得当,理论上你可以比使用PreparedStatement 获得一些轻微的速度改进,但这是一个很大的假设。 PreparedStatement 提供了比任何字符串转义函数都强大得多的行为,因此比较它们几乎是不公平的。需要经过净化的输入是值得PreparedStatement 超过手动转义的充分理由。
猜你喜欢
  • 2016-02-19
  • 1970-01-01
  • 2021-02-15
  • 2010-10-28
  • 1970-01-01
  • 2012-02-08
  • 1970-01-01
  • 2011-10-05
相关资源
最近更新 更多