我正在尝试使用PreparedStatement
类编写一个非常简单的查询。我在这里读到:Fail to convert to internal representation JDBC你不能参数化列名,只能参数化值。由于我的查询非常简单,唯一的价值是'我可以参数化count (*)
。
这是查询:
SELECT COUNT (*) FROM EZ_DAY
如果我尝试像这样参数化:
SELECT ? FROM EZ_DAY
我收到错误:
Fail to convert to internal representation
在getInt()
上使用ResultSet
方法时。
如何使用PreparedStatement
并参数化此查询中的某些内容以防止SQL注入?另外我知道你不能参数化列名,这包括表名吗?例如,我可以这样做:
SELECT COUNT (*) FROM ?
?
答案 0 :(得分:4)
该查询不能归入SQL注入。属于此类别的查询是您通过纯字符串连接构建的查询。例如:
String query = "SELECT COUNT(*) FROM EZ_DAY WHERE colX = " + stringParameter;
Statement stmt = con.createStatement(query);
ResultSet rs = stmt.executeQuery();
在您的情况下,没有要注入的参数,因此无法针对您的特定情况进行SQL注入攻击。
如果您需要防止SQL注入攻击,请使用PreparedStatement
并且不要连接查询。而是通过接口传递参数,这将为您转义任何无效字符:
String query = "SELECT COUNT(*) FROM EZ_DAY WHERE colX = ?";
PreparedStatement pstmt = con.prepareStatement(query);
pstmt.setString(1, stringParameter);
ResultSet rs = pstmt.executeQuery();
如果您需要构建动态查询,那么无论是使用纯字符串连接还是StringBuilder
:
//Common solution, still suffers from SQL injection
String query = "SELECT COUNT(*) FROM EZ_DAY WHERE 1 = 1 ";
if (stringParameter != null) {
query = query + = "AND colX = " + stringParameter;
}
相反,最好对参数使用COALESCE
或IFNULL
函数以避免出现这种情况:
//Better solution
String query = "SELECT COUNT(*) FROM EZ_DAY WHERE colx = COALESCE(?, colx)";
在上面的案例中:
如果参数的值不同于null
,则查询将如下所示:
String query = "SELECT COUNT(*) FROM EZ_DAY WHERE colx = ?";
如果参数的值为null
,则查询将如下所示:
String query = "SELECT COUNT(*) FROM EZ_DAY WHERE colx = colx";
在上一个示例中,您仍然可以使用PreparedStatement
并避免SQL注入攻击。
相关:
答案 1 :(得分:0)
如this post中所述,SQL注入可能导致非常严重的问题,如:
它不仅仅是可以受到影响的SQL。如果你没有使用绑定参数,甚至可以破坏JPQL。
最重要的是,在构建SQL语句时,不应该使用字符串连接。为此目的使用专用API: