mybaits的sql注入
MyBatis支持两种参数符号,一种是#,另一种是$。比如:
<select id="queryAll" resultMap="resultMap">
SELECT * FROM NEWS WHERE ID = #{id}
</select>
<select id="queryAll" resultMap="resultMap">
SELECT * FROM NEWS WHERE ID = ${id}
</select>
#{ }速度快,能防止sql注入,是预编译处理,MyBatis在处理#{}时,它会将sql中的#{}替换为?,然后调用PreparedStatement的set方法来赋值,传入字符串后,会在值两边加上单引号,如上面的值 “4,44,514”就会变成“ '4,44,514' ”;
${}是字符串替换,直接拼接到语句上。在处理{}时,它会将sql中的${ }替换为变量的值,传入的数据不会加两边加上单引号。
我们在日常使用中应该尽量使用#{},但是在某些情况下不得不使用${}这个时候就需要特别注意sql注入的问题。
1.模糊查询
错误示例:
Select * from news where title like ‘%#{title}%’
这种写法是错误的,如果只是像
Select * from news where title like ‘%${title}%’
这样简单的将#换成$而不再java代码层面进行验证限制。就很容易出现sql注入问题,我们可以这样写
select * from news where tile like concat(‘%’,#{title}, ‘%’)
2.in 之后的多个参数
错误示例
Select * from news where id in (#{ids})
正确用法为使用foreach,而不是将#替换为$。
<foreach collection="ids" item="item" open="("separatosr="," close=")">
#{ids}
</foreach>
order by 之后
这种场景应当在Java层面做映射,设置一个字段/表名数组,仅允许用户传入索引值。这样保证传入的字段或者表名都在白名单里面。需要注意的是在mybatis-generator自动生成的SQL语句中,order by使用的也是$,而like和in没有问题。