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

时间:2016-10-06 09:32:51

标签: java jdbc dynamic tablename

如何将表名作为参数放入SQL查询的安全方法是什么?您不能使用PreparedStatement将表名作为参数。可以使用Statement连接字符串以使用动态表名执行查询,但不建议使用SQL注入的风险。这样做的最佳方法是什么?

3 个答案:

答案 0 :(得分:3)

最好的方法是:

  1. 将表名放在用于分隔从一个数据库更改为另一个数据库的表名称的字符之间
  2. 并相应地转义提供的表名,以便SQL注入不再可能。
  3. 因此,例如在MySQL的情况下,表名的分隔符是反引号字符,我们通过简单地加倍来逃避它。

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

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

    通过这种方式,您可以注入表的名称,而不会冒着看到注入恶意代码的风险。

答案 1 :(得分:2)

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

答案 2 :(得分:1)

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

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

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

我无法想象一个用例,其中表名或列名可以是用户在表单字段中键入的字符串,这是允许参数化它们的唯一原因。