【问题标题】:How to escape SQL parameter in JDBC when PreparedStatement won't work?当 PreparedStatement 不起作用时,如何在 JDBC 中转义 SQL 参数?
【发布时间】:2016-04-29 18:51:09
【问题描述】:

我有一个要传递给 SQL 的字符串。为了防止 SQL 注入和其他引用和转义问题,最佳实践是使用 PreparedStatement?。例如:

val ps = conn.prepareStatement("select * from foo where name = ?")
ps.setString(1, name)

但对于某些 SQL 代码,这将不起作用。比如这里是PostgreSQL,试图创建一个视图。

 val ps = conn.prepareStatement("create temp view v1 as select * from foo where name = ?")
 ps.setString(1, name)
 val rs = ps.execute()

这会引发错误:

org.postgresql.util.PSQLException: ERROR: there is no parameter $1

它显然不允许create view 的参数。你如何解决这个问题并安全地逃脱字符串?

【问题讨论】:

  • 也许您应该只使用Statement 而不是PreparedStatement
  • 这将如何帮助我逃离name?我必须将它连接到字符串中,然后我就会受到 SQL 注入攻击。
  • 我明白你的意思。抱歉,在我发表评论之前,我应该更仔细地查看您想要做的事情。从那以后,我尝试了一些变体,但它们都会导致您收到相同的错误。似乎 PostgreSQL 真的不喜欢 DDL 中的参数替换,即使尝试从函数调用它也是如此。

标签: postgresql jdbc escaping postgresql-9.4


【解决方案1】:

Prepared statements 用于计划一个复杂的语句一次,然后使用不同的参数值执行多次(= 非常多次)。简单的语句从使用准备好的语句中没有明显的好处,因为计划它们是微不足道的。根本不支持 DDL 语句,因此这很可能是导致错误的原因,尽管错误消息令人困惑。

来自documentation

准备名称 [ ( data_type [, ...] ) ] AS 语句

声明
任何 SELECT、INSERT、UPDATE、DELETE 或 VALUES 语句。

PreparedStatement 类确实记录了您可以在 executeUpdate() 方法中使用 DDL,但从逻辑的角度来看,这只是无稽之谈,至少在 PostgreSQL 中是这样。

相反,您应该使用Statement,然后调用execute()executeUpdate()(有点奇怪,后一种方法支持 DDL 语句,因为没有执行更新)。

防止 SQL 注入

为了防止 SQL 注入,您可以使用一些 PostgreSQL 函数:

  • quote_literal() - 正如所料,这将引用文字参数值以确保查询安全。这不仅会阻止您访问Bobby Tables,还会阻止您访问Mr. O'Brien
  • quote_nullable() - 对于像上面这样的文字,但是当参数 IS NULL 时会生成正确的代码。
  • quote_identifier() - 将双引号可能导致规划器出现问题的任何表或列名称,例如表名称 from 与列 inttypefromSELECT int, type, from FROM from WHERE int = type 变为 SELECT "int", "type", "from" FROM "from" WHERE "int" = "type"

您可以直接在 SQL 语句中使用这些函数,然后让 PostgreSQL 处理讨厌的输入。

【讨论】:

  • 感谢您的回答,但我的主要问题是我想转义该字符串以防止引用问题和 SQL 注入。我应该在我的问题中更清楚地说明这一点。我会更新它。我看不出Statement 将如何帮助我逃避name 参数。
  • 您提到的功能(quote_literal 等)在这里没有帮助。我在应用程序代码中,调用 JDBC API。字符串参数需要在到达任何 PostgreSQL 函数(如 quote_literal)之前防止 SQL 注入。
猜你喜欢
  • 2017-11-21
  • 2021-07-19
  • 1970-01-01
  • 1970-01-01
  • 2012-04-07
  • 2021-11-12
  • 1970-01-01
  • 2012-09-26
  • 1970-01-01
相关资源
最近更新 更多