java CallableStatement vs SELECT关于SQL注入

时间:2016-04-26 08:23:37

标签: java sql-server postgresql 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这两种情况下,params被发送到数据库函数并在那里被视为函数本身定义的数据类型。 CallableStatement仅在数据类型不匹配时失败(在声明的函数和statement.set()中。

如果在两种情况下将params视为字符串(但在''之间),CallableStatement如何实际上比SELECT更安全。

感谢。

2 个答案:

答案 0 :(得分:2)

PreparedStatementCallableStatement都提供setXXX方法来设置参数。它们实际上并没有对参数进行消毒,它们只是在线上使用二进制类型,因此“在两种情况下,params都被视为字符串”部分是错误的。

PreparedStatement还提供了一些小的性能优势,因为在调用足够多次查询后,驱动程序实际上会创建一个服务器端预处理语句。

除非绝对必要,否则不应使用普通Statement,并始终使用setXXX方法,因为这就是它们的用途。

答案 1 :(得分:1)

据我所知,CallableStatement.setXXX()为您清理参数。所以它不仅仅是简单的字符串连接。

另一方面,当你连接String时,你会发现令人讨厌的攻击,比如停止前面的语句,然后开始一个新的攻击:`&#39 ;;删除表用户; -

有关xkcd的更多信息,请参阅