创建 sql 查询时使用 java.text.MessageFormat.format() 是否安全?

is it safe to use java.text.MessageFormat.format() when creating an sql query?

我正在使用 MessageFormat.format() 为我的 PreparedStatement 创建字符串。我读到使用 StringBuilder 可能是 sql 注入的原因。 MessageFormat 是否相同?

代码是这样的

String SQL
        = "select CT.SYS_CHANGE_OPERATION, CT.{0} as ID, t.*\n"
        + "from changetable (changes {1}, ?) as CT \n"
        + "left outer join {2} as t \n"
        + "on t.{3} = CT.{4} \n"
        + "order by CT.SYS_CHANGE_VERSION";

String finalSQL = MessageFormat.format(SQL, primaryKey, table, table, primaryKey, primaryKey);
        PreparedStatement pstmt = con.prepareStatement(finalSQL);

这不安全。 MessageFormat.format 只是将给定字符串中出现的 {x} 替换为给定对象,而不转义后者。 因此它相当于字符串连接。

要构建包含变量数据的 SQL 查询,应始终使用准备好的语句。

像填写 table 和列名 那样创建 SQL 字符串只会是不安全的(SQL 注入)变量字符串源于一些传递的输入。

因此 StringBuilder 甚至可能比 MessageFormat 更响亮(清晰)。另一方面,格式更具可读性。

由于命名占位符会更好,请考虑 Apache Common StringSubstitutor 等。

在每种情况下,代码检查器都可能会针对此 SQL 注入发出警告。

有时您可以使用

DatabaseMetaData metaData = connection.getMetaData();

并使用 table 和列名对元数据进行操作。

这是一种很大程度上独立于数据库供应商的 JDBC 查询数据库的方式。