用 like concat 不用 like,为了防止sql注入;#{}和${}的区别和用法;#{}预防SQL注入的原理

一、like concat 和 like

mybatis中为了防止sql注入,使用like语句时并不是直接使用,而是使用concat函数
 <if test="goodName != null  and goodName != ''"> and good_name like concat('%', #{goodName}, '%')</if>
concat()函数

1、功能:将多个字符串连接成成一个字符串。

2、语法:concat(str1, str2,)

说明:返回结果为连接参数产生的字符串,如果有任何一个参数为null,则返回值为null

二、#{}是会加上双引号,而${}匹配的是真实的值

#{}匹配的是一个占位符,相当于JDBC中的一个?,会对一些敏感的字符进行过滤,编译过后会对传递的值加上双引号,因此可以防止SQL注入问题。$ {}匹配的是真实传递的值,传递过后,会与sql语句进行字符串拼接。$ {}会与其他sql进行字符串拼接,不能预防sql注入问题。

2.1 用 #,入参 {“name”:“124”} , 打出的sql日志加上双引号 good_name = ‘123’

  <select id="getGoods" resultMap="BaseResultMap">
        select
        id,
        good_name,
        good_code,
        storage,
        goodstype,
        count,
        remark,
        target_value,
        target_value_string,
        target_big,
        data_status,
        brand_code,
        send_time
        from goods
        where data_status = '0'
        <if test="name !=null and name !=''">
        and good_name = #{name}
        </if>
    </select>
select* from goods where data_status = '0' and good_name = '123'

2.2 用 $,入参 {“name”:“124”} , 打出的sql日志,直接传递 good_name =123 会报错的**

 <select id="getGoods" resultMap="BaseResultMap">
        select
        id,
        good_name,
        good_code,
        storage,
        goodstype,
        count,
        remark,
        target_value,
        target_value_string,
        target_big,
        data_status,
        brand_code,
        send_time
        from goods
        where data_status = '0'
        <if test="name !=null and name !=''">
        and good_name = ${name}
        </if>
    </select>
    -- 报错的,good_name 字段是varchar类型,传整型 123 肯定报错。
select* from goods where data_status = '0' and good_name = 123

如果 {"name":"null"} ,打出的日志:select* from goods where data_status = '0' and good_name = null ; 什么结果都查不出

如果入参是  {"name":"null or 1=1"} 
select*from goods g  where data_status = '0' and good_name = null or 1=1; 就能查出所有数据了,sql注入风险

如果是 delete from user  goods  where data_status = '0' and good_name = null or 1=1,那就删除所有数据了

2.3 ${} 的使用场景

$ {}也有用武之地,我们都知道${}会产生字符串拼接,来生成一个新的字符串。

例如现在要进行模糊查询,查询user表中姓张的所有员工的信息。

sql语句为:select * from user where name like '张%'

此时如果传入的参数是 “张”
如果使用$ {}:select * from user where name like '${value}%'

生成的sql语句:select * from user where name like '张%'

如果使用#{}:select * from user where name like #{value}"%"

生成的sql语句:select * from user where name like '张'"%"

如果传入的参数是 “张%”
使用#{}:select * from user where name like #{value}

生成的sql语句:select * from user where name like '张%'

使用$ {}:select * from user where name like '${value}'

生成的sql语句:select * from user where name like '张%'

在这里插入图片描述

sql日志:       select*from user
				select*from user

2.4 #{}能够预防SQL注入的原理

MyBatis的#{}之所以能够预防SQL注入是因为底层使用了PreparedStatement类的setString()方法来设置参数,此方法会获取传递进来的参数的每个字符,然后进行循环对比,如果发现有敏感字符(如:单引号、双引号等),则会在前面加上一个’/'代表转义此符号,让其变为一个普通的字符串,不参与SQL语句的生成,达到防止SQL注入的效果。

2.5 #{}和${}用法总结

其次${}本身设计的初衷就是为了参与SQL语句的语法生成,自然而然会导致SQL注入的问题(不会考虑字符过滤问题)。

(1)#{}在使用时,会根据传递进来的值来选择是否加上双引号,因此我们传递参数的时候一般都是直接传递,不用加双引号,${}则不会,我们需要手动加

(2)在传递一个参数时,我们说了#{}中可以写任意的值, 则必须使用 v a l u e ;即: {}则必须使用value;即: 则必须使用value;即:{value}

(3)#{}针对SQL注入进行了字符过滤,${}则只是作为普通传值,并没有考虑到这些问题

(4)#{}的应用场景是为给SQL语句的where字句传递条件值,${}的应用场景是为了传递一些需要参与SQL语句语法生成的值。

参考:https://blog.csdn.net/Bb15070047748/article/details/107188167

  • 16
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值