#{xxx},使用的是PreparedStatement,会有类型转换,所以比较安全;
${xxx},使用字符串拼接,可以SQL注入;
like查询不小心会有漏动,正确写法如下:
Mysql: select * from t_user where name like concat('%', #{name}, '%')
Oracle: select * from t_user where name like '%' || #{name} || '%'
SQLServer: select * from t_user where name like '%' + #{name} + '%'
关于上述结论可以在xml中验证
1、select * from test where id = #{id}
随便传个id执行后可以在日志中看到如下结果
select * from test where id = ?
原理是采用了jdbc中的PreparedStatement,PreparedStatement是我们很熟悉的Statement的子类,它的对象包含了编译好的sql语句。这种“准备好”的方式不仅能提高安全性,而且在多次执行一个sql时,能够提高效率,原因是sql已编译好,再次执行时无需再编译。
2、select * from test order by ${list}
随便传个参数例如id执行后可以在日志中看到如下结果
select * from test order by id
这种是字符串拼接的,存在sql注入隐患
在mybatis中,”${xxx}”这样格式的参数会直接参与sql编译,从而不能避免注入攻击。但涉及到动态表名和列名时,只能使用“${xxx}”这样的参数格式,所以,这样的参数需要我们在代码中手工进行处理来防止注入。
所以尽量用#{}这种方式传参数,如果用到了${}方式要手动过滤sql注入。