java - PreparedStatement IN 子句替代方案?

标签 java security jdbc prepared-statement in-clause

使用 SQL 的最佳解决方法是什么 IN具有 java.sql.PreparedStatement 实例的子句,由于 SQL 注入(inject)攻击安全问题,不支持多个值:1 ?占位符代表一个值,而不是一组值。

考虑以下 SQL 语句:

SELECT my_column FROM my_table where search_column IN (?)

使用preparedStatement.setString( 1, "'A', 'B', 'C'" );本质上是对使用?原因的解决方法的非工作尝试。首先。

有哪些可用的解决方法?

最佳答案

Jeanne Boyarsky 的 Batching Select Statements in JDBC 中提供了对各种可用选项及其优缺点的分析。 JavaRanch Journal 上的条目。

建议的选项是:

  • 准备SELECT my_column FROM my_table WHERE search_column = ? ,对每个值执行它并在客户端对结果进行 UNION。仅需要一份准备好的声明。缓慢而痛苦。
  • 准备SELECT my_column FROM my_table WHERE search_column IN (?,?,?)并执行它。每个 size-of-IN-list 需要一个准备好的语句。快速且明显。
  • 准备SELECT my_column FROM my_table WHERE search_column = ? ; SELECT my_column FROM my_table WHERE search_column = ? ; ...并执行它。 [或使用UNION ALL代替那些分号。 --ed] 每个 size-of-IN-list 需要一个准备好的语句。慢得愚蠢,严格来说比 WHERE search_column IN (?,?,?) 还要差,所以我不知道博主为什么这么建议。
  • 使用存储过程构建结果集。
  • 准备N个不同大小的IN列表查询;例如,具有 2、10 和 50 个值。要搜索具有 6 个不同值的 IN 列表,请填充 size-10 查询,使其看起来像 SELECT my_column FROM my_table WHERE search_column IN (1,2,3,4,5,6,6,6,6,6) 。任何像样的服务器都会在运行查询之前优化重复值。

这些选项都不理想。

如果您使用 JDBC4 和支持 x = ANY(y) 的服务器,这是最佳选择,就是使用PreparedStatement.setArrayBoris's anwser 中所述.

似乎没有办法制作setArray不过,可以使用 IN 列表。

<小时/>

有时 SQL 语句在运行时加载(例如,从属性文件),但需要可变数量的参数。在这种情况下,首先定义查询:

query=SELECT * FROM table t WHERE t.column IN (?)

接下来,加载查询。然后在运行之前确定参数的数量。一旦知道参数计数,请运行:

sql = any( sql, count );

例如:

/**
 * Converts a SQL statement containing exactly one IN clause to an IN clause
 * using multiple comma-delimited parameters.
 *
 * @param sql The SQL statement string with one IN clause.
 * @param params The number of parameters the SQL statement requires.
 * @return The SQL statement with (?) replaced with multiple parameter
 * placeholders.
 */
public static String any(String sql, final int params) {
    // Create a comma-delimited list based on the number of parameters.
    final StringBuilder sb = new StringBuilder(
        String.join(", ", Collections.nCopies(possibleValue.size(), "?")));

    // For more than 1 parameter, replace the single parameter with
    // multiple parameter placeholders.
    if (sb.length() > 1) {
        sql = sql.replace("(?)", "(" + sb + ")");
    }

    // Return the modified comma-delimited list of parameters.
    return sql;
}

对于某些不支持通过 JDBC 4 规范传递数组的数据库,此方法可以帮助转换缓慢的 = ?进得更快IN (?)子句条件,然后可以通过调用 any 来扩展该条件方法。

关于java - PreparedStatement IN 子句替代方案?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46442229/

相关文章:

java - 加载 JDBC 驱动程序

javax.crypto JDK 源代码,再次

java - ImageIcon 不显示在 java 中

python - Python.requests 安全吗?

php - 跨站点伪造 (CSRF) 和公共(public)应用程序接口(interface)

mysql - JBoss 7.1.1 中的 java.lang.ClassNotFoundException : com. mysql.jdbc.Driver - 出了什么问题?

java - Mysql 连接关闭时出现错误 "Operation not allowed after ResultSet closed"

java - 没有任何参数的AWS Lambda

Java Web Start 启动画面不显示

asp.net-mvc - 如何向 MVC 应用程序公开内置安全性和用户管理?