起因:#{}和${}的区别是什么
${}是字符串替换,#{}是预处理;使用#{}可以有效的防止SQL注入,提高系统安全性。
Mybatis在处理${}时,就是把${}直接替换成变量的值。而Mybatis在处理#{}时,会对sql语句进行预处理,将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
下面就让我们举例说明:
假设有一个网站,用户可以通过输入用户名和密码来登录,然后系统会检查数据库中是否存在匹配的用户名和密码。下面是一个示例:
原始登录代码(容易受到SQL注入攻击):
String username = request.getParameter("username");
String password = request.getParameter("password");
String query = "SELECT * FROM users WHERE username='" + username + "' AND password='" + password + "'";
在上面的示例中,用户输入的 username
和 password
直接嵌入到SQL查询中,没有经过验证或处理。这样的代码容易受到SQL注入攻击的影响。
SQL注入攻击示例:
假设攻击者输入以下内容作为用户名:
' OR '1'='1
当这个输入被插入到原始查询中时,查询将变成
SELECT * FROM users WHERE username='' OR '1'='1' AND password='';
这个查询中的条件 '1'='1'
总是为真,因此它将返回所有用户的记录,而不管密码是否匹配。攻击者可能成功登录为任何用户,因为他们绕过了身份验证。
修正后的登录代码(防止SQL注入):
String username = request.getParameter("username");
String password = request.getParameter("password");
// 使用预编译语句或参数化查询来避免SQL注入
String query = "SELECT * FROM users WHERE username=? AND password=?";
PreparedStatement preparedStatement = connection.prepareStatement(query);
preparedStatement.setString(1, username);
preparedStatement.setString(2, password);
结论:在修正后的代码中,我们使用参数化查询,将用户输入的数据作为参数传递给SQL查询,而不是直接嵌入查询字符串。这可以有效地防止SQL注入攻击,因为数据库系统知道这些参数是数据,而不是SQL代码的一部分。