mybatis的$存在安全问题,为什么又不得不用?
1、mybatis的官网关于$和#的字符串替换符号区别描述如下:
http://www.mybatis.org/mybatis-3/zh/sqlmap-xml.html#Parameters
上面的意思是说:假如参数columnName的值是ID,那么${columnName}会变成ID,#{columnName}会被替换成'ID',变成了字符串,注意引号。
2、对于上面的描述谈下自己的理解:
假如你使用符号#,那么输入的参数会被看做字符串,假如你输入参数ID,最后就会变成字符串'ID';
假如上面的的参数ID表示数据表的列名,你想根据这一列进行排序,你所期望的sql语句大概是这样:select * from tb_name order by ID,可是,你使用#符号,在xxxMapper.xml中写成下列模式:
1 <select id="queryByParams" parameterType="MyTestDO" resultMap="MyTestMap"> 2 SELECT * FROM tb_name order by #{ID} 3 </select>
最终生成的sql语句其实是这个样子:select * from tb_name order by 'ID',这样就无法实现根据列名ID进行排序的目的,因为没有列名'ID',只有列名ID,但是sql语法没有问题,可以执行。
对于这种情况,为了防止sql注入问题,我们只能限制传入的参数内容或者形式,不能让任意的参数内容传入进来。比如下面的代码:
1 String orderByType=request.getParameter(ORDER_BY_TYPE); 2 if(StringUtils.isNotEmpty(orderByType)){ 3 if(orderByType.equals("desc")||orderByType.equals("asc")){ 4 sqlParamFromRequest(sqlParams, ORDER_BY_TYPE); 5 } 6 } 7 8 String orderparam=request.getParameter("orderParam"); 9 if(StringUtils.isNotEmpty(orderparam)) { 10 11 if (orderparam.equals("normal_counting+abnormal_counting")) { 12 sqlParams.put("orderParam", "addnew"); 13 14 } else if(orderparam.equals("normal_counting")||orderparam.equals("abnormal_counting")||orderparam.equals("emulator_counting")||orderparam.equals("app_channel")){ 15 16 sqlParamFromRequest(sqlParams, ORDER_BY_PARME); 17 } 18 }
3、有些资料说like不能使用#符号,我实际测试,是可以用的
对于下面需要使用拼接的情况,是可以使用#符号的,像下面写的这样:
1 <select id="queryByParams" parameterType="MyTestDO" resultMap="MyTestMap"> 2 SELECT * FROM tb_shen 3 WHERE 1=1 4 <if test="name !=null">AND name LIKE CONCAT('%',#{name},'%')</if> 5 </select>
实际测试情况如下:(和上面的例子sql不符,因为这是后面修改的)
但是如果你写成下面的样子,在mybatis预处理的时候,是有问题的
1 <select id="queryByParams" parameterType="MyTestDO" resultMap="MyTestMap"> 2 SELECT * FROM tb_shen 3 WHERE 1=1 4 <if test="name !=null">AND name LIKE CONCAT('%','#{name}','%')</if> 5 </select>