如何使用Java在PostgreSQL中安全地转义SQL的任意字符串

我有一个特殊情况,要求我从用户提供的输入值生成SQL WHERE子句的一部分。 我想防止任何类型的SQL注入漏洞。 我想出了以下代码:

private String encodeSafeSqlStrForPostgresSQL(String str) { //Replace all apostrophes with double apostrophes String safeStr = str.replace("'", "''"); //Replace all backslashes with double backslashes safeStr = safeStr.replace("\\", "\\\\"); //Replace all non-alphanumeric and punctuation characters (per ASCII only) safeStr = safeStr.replaceAll("[^\\p{Alnum}\\p{Punct}]", ""); //Use PostgreSQL's special escape string modifier safeStr = "E'" + safeStr + "'"; return safeStr; } 

问题:

  • 你看到有什么问题吗?
  • 你能提供更好的解决方案吗?
  • 有没有现有的图书馆来帮助解决这个问题?

笔记:

  • 这是关于SO和其他地方的常见问题,但我见过的唯一答案是始终使用PreparedStatements。 Fwiw,我正在使用JasperReports。 我想将查询保留在JasperReports中。 用于查询参数处理的内置Jasper参数函数(包括X {}函数)不足以满足参数化需要。 我可以尝试创建一个自定义的Jasper QueryExecutor,它允许我注入我自己的X {}函数,但这比使用Jasper的$ P!{}语法生成动态SQL where子句更复杂。

  • 我查看了OWASP库 。 他们还没有PostgresSQL编解码器。 我查看了OracleCodec,但它的转移似乎过于简单化了。 我不确定这对防止SQL注入攻击有多大帮助。

  • 在我的代码中,我添加了E,以便不依赖于PostgreSQL的standard_conforming_strings设置。 理想情况下,我不必添加它,然后该函数不必是PostgreSQL特定的。 更多信息: http : //www.postgresql.org/docs/9.0/static/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-ESCAPE 。

理想情况下,我会喜欢一种更通用,更健壮的解决方案,我知道这种解决方案是安全的并支持所有可能的UTF-8字符串。

最简单的方法是使用PostgreSQL的Dollar Quoting与一个小的随机标签组合:

  • 对于每次调用,计算一个小的随机标记(例如4个字符) (冗余)
  • 查看quote标记是否是输入字符串的一部分。
  • 如果是,则重新计算新的随机标记。
  • 否则构建您的查询,如下所示:

     $tag$inputString$tag$ 

这样您就可以避免使用不同嵌套引用技术的麻烦,还可以使用随机标记设置移动目标。

根据您的安全要求,这可能会起作用。 🙂

我在这里问了一个类似的问题 ,但我认为最好的办法是使用org.postgresql.core.Utils.escapeLiteral 。 这是一个Postgres库,所以使用它应该是安全的。 如果/当Postgres添加新的字符串分隔符时,应该更新此方法。