在 JDBC 查询中使用 table 名称作为参数的安全方法

Safe way to use table name as parameter in JDBC query

将 table 名称作为参数放入 SQL 查询的安全方法是什么?您不能将 table 名称作为参数使用 PreparedStatement. Concatenating string to execute query with dynamic table name using Statement 是可能的,但不建议这样做,因为存在 SQL 注入的风险。执行此操作的最佳方法是什么?

我会尝试解决设计问题,因此您不必动态设置 table 名称。如果这不可能,我会选择一种设计,您可以在其中管理可用 table 的列表,用户可以从中选择一个,按 ID,这样您就可以从所选择的 table 中检索真实的 table 名称id 并用它替换 table 名称占位符,避免在 table 名称替换中注入任何 sql 的机会。

最好的方法是:

  1. 将您的 table 名称放在用于分隔从一个数据库更改为另一个 table 的名称的字符之间
  2. 并相应地转义所提供的 table 名称,这样 SQL 注入将不再可能。

因此,例如在 MySQL 的情况下,table 名称的定界符是反引号字符,我们只需将其加倍即可将其转义。

如果您的查询是 SELECT foo from bar,您可以将查询重写为下一个:

 String query = String.format("SELECT foo from `%s`", tableName.replace("`", "``"));

通过这种方式,您可以注入 table 的名称,而无需冒看到注入某些恶意代码的风险。

在动态 JDBC 查询中只允许实际参数的背后有一个基本原理:参数可以来自外部并且可以取任何值,而 table 和列名是 静态.

参数化 table 或列名可能有一些用例,主要是当不同的 table 具有几乎相同的结构时,并且由于 DRY 原则,您不想重复多次同一查询仅更改 table (或列)名称。但是在那个用例中,程序员可以完全控制将要替换的名称,并且应该仔细测试它们中的任何一个都没有拼写错误=>这里没有 SQL 注入的可能性,而且它是安全的替换查询字符串中的 table 名称。

这对于在 Internet 上公开的 Web 应用程序来说是完全不同的,在该应用程序中,查询将使用在表单字段中输入的内容,因为这里可能发生任何事情,包括用于终止原始无害查询并伪造新的有害查询的半列一个 => SQL 注入,如果你只是连接字符串而不是正确构建参数化查询。

我无法想象 table 名称或列名称可能是用户在表单字段中键入的字符串的用例,这将是允许对其进行参数化的唯一原因。