考虑一个假设的情况,我必须根据userId从数据库中检索一些细节,下面给出了示例代码
private String getpassword(String username) {
PreparedStatement statement = null;
ResultSet resultSet = null;
Connection conn = null;
final String selectQuery = "SELECT password FROM " + "users WHERE username=?";
try {
conn = dataSource.getConnection();
statement = conn.prepareStatement(selectQuery);
statement.setString(1, username);
resultSet = statement.executeQuery();
if (resultSet.next()) {
}
} catch (SQLException e) {
// log it
}
//return
}
此用户名实际上来自客户端,用户可以篡改数据(如果他愿意)。因此,preparedStatements将阻止接受引号并仅将过滤后的SQL形式发送到数据库。
例如:我可以提供username ='或1 = 1,它将是一个有效的SQL语句。但是如果驱动程序从用户输入中删除引号,那么它们将阻止sql注入。
对它的一般理解是什么?
答案 0 :(得分:4)
根据这个,是的:http://en.wikipedia.org/wiki/SQL_injection
在这种情况下,语句已经被编译,注入的代码将不再被解释(因此也不会被执行)。
答案 1 :(得分:3)
使用参数和预准备语句确实可以防止SQL注入攻击,即传递“'或1 = 1”不会导致返回意外数据。但是,如果在任何阶段将数据显示给用户,则需要确保生成的HTML不会受到从数据库返回的用户输入的影响
例如,如果您的网页显示:
Hello, ${username}
如果用户名是
<script>alert('I could have been more malicious')</script>
会导致XSS或CSRF攻击。
N.B。
Hello, ${fn:escapeXml(username)}
会更安全(JSP代码)。
一个很好的参考是:
答案 2 :(得分:0)
用户名和查询将作为两个单独的东西发送到数据库,数据库引擎将负责将两者重新组合在一起。在读取参数时,引擎已经编译了查询,因此这两个从不被视为同一语句的一部分。