2016-01-23 121 views
2

我有一个字符串,我想传递给SQL。为防止SQL注入和其他引用和转义问题,最佳做法是使用PreparedStatement?。例如:当PreparedStatement不起作用时,如何在JDBC中转义SQL参数?

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。你如何解决这个问题并且安全地逃离弦线?

+1

也许你应该只使用'Statement'而不是'PreparedStatement'? –

+0

这将如何帮助我逃脱'名称'?我不得不将它连接到字符串,然后我打开SQL注入攻击。 –

+0

我明白你的意思了。对不起,在我评论之前,我应该更仔细地看看你想做什么。我已经尝试了一些变化,但它们都会导致您收到相同的错误。看来PostgreSQL真的不喜欢DDL中的参数替换,即使试图从函数调用它。 –

回答

0

准备语句用于计划一次复杂语句,然后使用不同参数值执行多次(=很多次)。简单的陈述没有使用准备好的陈述的显着好处,因为计划它们是微不足道的。 DDL语句根本不被支持,所以这很可能是错误的原因,尽管错误信息很混乱。

documentation

PREPARE name [ (data_type [, ...]) ] AS statement

statement
Any SELECT, INSERT, UPDATE, DELETE, or VALUES statement.

PreparedStatement类完成,你可以在executeUpdate()方法使用DDL,但是从逻辑的角度来看,这只是无稽之谈,至少在PostgreSQL的文档。

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

防止SQL注入

为了防止SQL注入,你可以使用一些PostgreSQL的功能:

  • quote_literal() - 可以想见,这将引用一段文字的参数值在查询中是安全的。这不仅会阻止你从Bobby Tables,而且也阻止你从Mr. O'Brien
  • quote_nullable() - 对于上述文字,但会在参数IS NULL时生成正确的代码。
  • quote_identifier() - 将双引号,可能导致问题的策划者,像列inttypefrom表名from任何表或列名:SELECT int, type, from FROM from WHERE int = type成为SELECT "int", "type", "from" FROM "from" WHERE "int" = "type"

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

+0

谢谢你的回答,但我的主要问题是我想逃避该字符串以防止引用问题和SQL注入。我应该在我的问题上做得更清楚。我会更新它。我没有看到'Statement'如何帮助我转义'name'参数。 –

+1

你提到的函数('quote_literal'等)在这里没有帮助。我在应用程序代码中调用JDBC API。字符串参数在到达任何PostgreSQL函数(如'quote_literal')之前需要进行SQL注入保护。 –

相关问题