Mybatis中 #{} 和 ${} 的区别!

前言


下图为两条sql:

从图上可以看出 mu.row_id in(You can't use 'macro parameter character #' in math mode{userId}) 和 wwlr.LabelId in(#{userId}),其中userId是传进来一个字符串类型的参数,参数的样子是这样的“4,44,514”,问题就出在这个参数传进来后#和处理的方式是不一样的。

 

区别


 

 

1、#{ }是预编译处理,MyBatis在处理#{ }时,它会将sql中的#{ }替换为?,然后调用PreparedStatement的set方法来赋值,传入字符串后,会在值两边加上单引号,如上面的值 “4,44,514”就会变成“ '4,44,514' ”;

 

2、${ }是字符串替换,在处理{ }是字符串替换, MyBatis在处理{ }时,它会将sql中的${ }替换为变量的值,传入的数据不会加两边加上单引号。

 

注意:使用${ }会导致sql注入,不利于系统的安全性!

 

SQL注入:

  就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。常见的有匿名登录(在登录框输入恶意的字符串)、借助异常获取数据库信息等

 

 

 

应用场合:


 

 

1、#{ }:主要用户获取DAO中的参数数据,在映射文件的SQL语句中出现#{}表达式,底层会创建预编译的SQL;

 

2、${ }:主要用于获取配置文件数据接口中的参数信息当{ }:主要用于获取配置文件数据,DAO接口中的参数信息,当出现在映射文件的SQL语句中时创建的不是预编译的SQL,而是字符串的拼接,有可能会导致SQL注入问题.所以一般使用$接收dao参数时,这些参数一般是字段名,表名等,例如order by {column}。

 

注:

 

${}获取DAO参数数据时,参数必须使用@param注解进行修饰或者使用下标或者参数#{param1}形式;

 

#{}获取DAO参数数据时,假如参数个数多于一个可有选择的使用@param。

 

 

 

解决办法

 

1、快速解决

 

最快的方法就是把#直接替换成$,这样问题应该就可以解决了。

 

但是,我很无语,我确没有解决。

 

本地跑代码一点问题都没有,部署到公司的docker上问题一样没解决,给人的感觉就是代码根本没有从#变$。

 

大家都知道其实是有危险性,会容易被注入,具我所知道,我们公司的是会加一层防止注入的功能,所以不知道是不是这个功能把的其实是有危险性,会容易被sql注入,具我所知道,我们公司的docker是会加一层防止 sql注入的功能 ,所以不知道是不是这个功能把的无效掉了。

 

当然,我也没有去再到服务上打出sql来看一下,因为本来$就是不太安全的,所以我换了一种方式处理。

 

2、foreach标签的使用

<select id="getUser" resultType="UserBean">
          select * from md_user where id in
                <foreach collection="userIds" item="ids" open="(" close=")" separator=",">
                    #{ids}
                </foreach>
 </select>

foreach标签的属性: 

     item:表示集合中每一个元素进行迭代时的别名。

  index: 指定一个名称,表示在迭代的过程中,每次迭代到的位置。

  open:表示该语句以什么开始(既然是in条件语句,必然是 ' ( ' 开始)

  separator: 表示每次进行迭代的时候以什么符号作为分隔符(既然是in条件语句,必然是 ' , ' 分隔)

  close: 表示该语句以什么结束(既然是in条件语句,必然是 ' ) ' 结束)

  collection:最关键,并且最容易出错的属性。需注意,该属性必须指定,不同情况下,该属性值是不同的,主要有三种情况:

    若传入的参数是单参数且类型为一个List的时候,属性值为list;

    若传入的参数是单参数且类型为一个数组的时候,属性值为array;

    若传入的参数为多参数时,就需要封装为一个map集合进行处理。属性值为Map的key;

 

foreach标签主要用于构建in条件,他可以在sql中对集合进行迭代。

 

那对于我们项目中的改造,其实就是把原来传进来的字符型参数变成List,这样问题就完美的解决了,既实现了我们的功能 ,又解决了安全性问题。

 

posted @ 2019-07-24 14:05  胡大辉  阅读(1513)  评论(0编辑  收藏  举报