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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9741206/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-16 07:00:55  来源:igfitidea点击:

How to safely escape arbitrary strings for SQL in PostgreSQL using Java

javasqlpostgresql

提问by kaliatech

I have a special caserequiring that I generate part of a SQL WHERE clause from user supplied input values. I want to prevent any sort of SQL Injection vulnerability. I've come up with the following code:

我有一个特殊情况,要求我从用户提供的输入值生成 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;
}

Questions:

问题:

  • Do you see any issues?
  • Can you provide a better solution?
  • Are there any existing libraries to help with this?
  • 你看到任何问题吗?
  • 你能提供更好的解决方案吗?
  • 是否有任何现有的图书馆可以帮助解决这个问题?

Notes:

笔记:

  • This is a common question on SO and elsewhere, but the only answer I've seen is to always use PreparedStatements. Fwiw, I'm using JasperReports. I want to keep the query inside of JasperReports. The built-in Jasper parameter functions for query parameter handling (including the X{} functions) are not sufficient for what I need to parametrize. I could try creating a custom Jasper QueryExecutor that would allow me to inject my own X{} functions, but that's more complicated than just generating a dynamic SQL where clause with Jasper's $P!{} syntax.

  • I looked at the OWASP libraries. They do not have a PostgresSQL codec yet. I looked at the OracleCodecthough and its escaping seemed simplistic. I'm not sure it would be of much helping preventing SQL injection attacks.

  • In my code I'm adding the E so as to not be dependent on PostgreSQL's standard_conforming_strings setting. Ideally I wouldn't have to add that and then the function wouldn't have to be PostgreSQL specific. More info: http://www.postgresql.org/docs/9.0/static/sql-syntax-lexical.html#SQL-SYNTAX-STRINGS-ESCAPE.

  • 这是 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

Ideally I would've liked a more generic and robust solution that I knew would be safe and support all possible UTF-8 strings.

理想情况下,我会喜欢一个更通用、更强大的解决方案,我知道它是安全的并且支持所有可能的 UTF-8 字符串。

采纳答案by A.H.

The most easiest way would be to use PostgreSQL's Dollar Quotingin the combination with a small randomtag:

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

  • For each invocation calculate a small, random tag (e.g 4 characters)(redundant)
  • Look whether or not the quote tag is part of the input string.
  • If it is, recalculate a new random tag.
  • Otherwise build your query like this:

    $tag$inputString$tag$
    
  • 对于每次调用计算一个小的随机标签(例如 4 个字符)(冗余)
  • 查看引号标记是否是输入字符串的一部分。
  • 如果是,重新计算一个新的随机标签。
  • 否则像这样构建您的查询:

    $tag$inputString$tag$
    

This way you escape the whole hassle of different nested quoting techniques andyou also set up a moving target by using a random tag.

通过这种方式,您可以避开不同嵌套引用技术的全部麻烦,并且您还可以使用随机标签设置移动目标。

Depending on your security requirements this might do the job or not. :-)

根据您的安全要求,这可能会起作用,也可能不起作用。:-)

回答by sixtyfootersdude

I asked a similar questionhere, but I think that the best thing to do is to use org.postgresql.core.Utils.escapeLiteral. This is a Postgres library so using it should be safe. If/when Postgres adds new string delimiters this method should be updated.

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