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没有问题。

posted @ 2020-07-20 19:49  大嘤熊  阅读(345)  评论(0编辑  收藏  举报