java CallableStatement 与 SELECT 关于 SQL 注入
java CallableStatement vs SELECT regards to SQL injection
我希望能更好地理解 CallableStatement。
所以情况是我的 postgre 数据库中有一个存储函数。
从 java 调用这些函数,其中参数是用户输入(HTTP POST 参数)我不得不担心 SQL 注入。
所以在 java 中这样做:
String statementSQL = "SELECT my_function(" + toPostgresString(person.getEmail()) + "," + toPostgresString(person.getPhone()) + "," + toPostgresString(person.getDealType())+ ");";
其中
private static String toPostgresString(String value) {
if (value == null || value.equals("")) {
return POSTGRES.NULL;
} else {
return "'" + value + "'";
}
}
后一种方法确保所有参数都被视为字符串,但我读到当参数是恶意的时,这种解决方案仍然很危险。
所以我尝试使用 CallableStatements,因为据说它们更安全。
CallableStatement statement = connection.prepareCall(" { call my_function( ?, ?, ? ) } ");
statement.setString(1, person.email());
statement.setString(2, person.phone());
statement.setString(3, person.getDealType());
statement.execute();
statement.close();
问题: 在 SELECT 和 CallableStatement 两种情况下,参数都被发送到数据库函数,并在那里被视为由函数本身定义的数据类型。 CallableStatement 只有在数据类型不匹配时才会失败(在声明的函数和 statement.set().
CallableStatement 实际上比 SELECT 更安全,在这两种情况下,参数都被视为字符串(但在 '' 之间)。
谢谢。
据我所知,CallableStatement.setXXX()
会为您清理参数。所以它不仅仅是简单的字符串连接。
另一方面,当您连接 String 时,您可能会遇到恶意攻击,例如停止上一个语句,然后开始一个新语句:`';删除 table 用户; --
更多信息见xkcd。
PreparedStatement
和CallableStatement
都提供了setXXX
方法来设置参数。他们实际上并没有清理参数,他们只是在网络上使用二进制类型,所以 "in both cases the params are treated as string" 部分是错误的。
PreparedStatement
还提供了一些小的性能优势,因为在查询被调用足够多次后,驱动程序实际上会创建服务器端准备好的语句。
除非绝对必要,否则永远不要使用普通的 Statement
,并且始终使用 setXXX
方法,因为这就是它们的用途。
我希望能更好地理解 CallableStatement。 所以情况是我的 postgre 数据库中有一个存储函数。
从 java 调用这些函数,其中参数是用户输入(HTTP POST 参数)我不得不担心 SQL 注入。
所以在 java 中这样做:
String statementSQL = "SELECT my_function(" + toPostgresString(person.getEmail()) + "," + toPostgresString(person.getPhone()) + "," + toPostgresString(person.getDealType())+ ");";
其中
private static String toPostgresString(String value) {
if (value == null || value.equals("")) {
return POSTGRES.NULL;
} else {
return "'" + value + "'";
}
}
后一种方法确保所有参数都被视为字符串,但我读到当参数是恶意的时,这种解决方案仍然很危险。
所以我尝试使用 CallableStatements,因为据说它们更安全。
CallableStatement statement = connection.prepareCall(" { call my_function( ?, ?, ? ) } ");
statement.setString(1, person.email());
statement.setString(2, person.phone());
statement.setString(3, person.getDealType());
statement.execute();
statement.close();
问题: 在 SELECT 和 CallableStatement 两种情况下,参数都被发送到数据库函数,并在那里被视为由函数本身定义的数据类型。 CallableStatement 只有在数据类型不匹配时才会失败(在声明的函数和 statement.set().
CallableStatement 实际上比 SELECT 更安全,在这两种情况下,参数都被视为字符串(但在 '' 之间)。
谢谢。
据我所知,CallableStatement.setXXX()
会为您清理参数。所以它不仅仅是简单的字符串连接。
另一方面,当您连接 String 时,您可能会遇到恶意攻击,例如停止上一个语句,然后开始一个新语句:`';删除 table 用户; --
更多信息见xkcd。
PreparedStatement
和CallableStatement
都提供了setXXX
方法来设置参数。他们实际上并没有清理参数,他们只是在网络上使用二进制类型,所以 "in both cases the params are treated as string" 部分是错误的。
PreparedStatement
还提供了一些小的性能优势,因为在查询被调用足够多次后,驱动程序实际上会创建服务器端准备好的语句。
除非绝对必要,否则永远不要使用普通的 Statement
,并且始终使用 setXXX
方法,因为这就是它们的用途。