MyBatis之bind标签详解,bind预防SQL注入案例及详解

1、bind标签

  • bind 标签可以使用 OGNL 表达式创建一个变量井将其绑定到上下文中

语法:

<bind name = "需要绑定的变量"    value = "绑定的最终值" />

  • name:为上下文的变量,如SQL中存在#{userName}变量,这里name就填写userName
  • value:绑定变量的最终值,如name="userName",那么value就是#{userName}的最终实际值,可以对传递的参数进行处理,如:value = " '%' + userName + '%' ",给传入的userName拼接前后%符号。

2、作用

1>兼容不同数据库之间的SQL语法差异,对数据库迁移友好

由于不同数据库的部分SQL写法存在差异,使用bind可以适配不同数据库之间的差异

如:模糊查询时,使用concat字符串拼接函数,在MySQL中支持多个参数,而Oracle中只能写两个参数,如下:

MySQL写法:

select id,serial from payment 
where
serial like concat("%",#{serial},"%")

Oracle写法:

select id,serial from payment
where
serial like concat("%",concat(#{serial},"%"))

因此,在Oracle迁移至MySQL时,会导致mybatis报错,我们可以使用bind标签直接兼容,如下:

select id,name from payment
where
<bind name="name" value="'%'+name+'%'" />
name  like #{name}  --name实际是bind标签中的value

2>防止SQL注入

以模糊查询为例,当我们不使用concat函数,直接使用SQL字符串拼接时,如下:

select id,serial from payment
where
serial like "%${serial}%"
--注意:Oracle写法为:"%"||${serial}||"%"

注意:这里只能为:"%${serial}%",不能是"%#{serial}%"

  • "%${serial}%":${serial}会看成字符串占位符,当运行SQL时直接替换该部分
  • "%#{serial}%":#{serial}在字符串拼接时,不会生效,直接就是一个"%#{serial}%"字符串

我们测试上述SQL模糊查询语句,SQL注入案例:

<1>MySQL存在payment表数据

<2>mybatis映射XML
<select id="getBySerial" resultMap="payMap">
    select id,serial from payment where
    serial like "%${serial}%"
</select>
<3>controller接口

service、dao层代码直接省略了,没有任何处理,直接会调用xml中的SQL

@RequestMapping("/payment/getBySerial")
public R<List<PaymentDTO>> getBySerial(PaymentDTO dto){
	return R.ok(paymentService.getBySerial(dto));
}
<4>测试

测试正常请求:http://127.0.0.1:6061/payment/getBySerial?serial=O

此时执行的SQL语句为:

select id,serial from payment where
serial like "%O%"

测试SQL注入请求:http://127.0.0.1:6061/payment/getBySerial?serial=O" or 1=1 or "serial=O

此时执行的SQL语句为:

select id,serial from payment where 
serial like "%O" or 1=1 or "serial=O%"

!!!or 1 = 1 :过滤条件直接失效,能获取到表中的所有数据!,如下:

<5>bind防止SQL注入修改

因此,上述写法我们不能使用#{}去防止SQL注入,在不使用SQL函数和java代码不拼接%的情况下,我们想预防SQL注入,可以使用bind标签+#{}替换${}拼接方式,案例如下:

  • 更改xml中的SQL,其他代码不动:
select id,serial from payment where
<bind name="serial" value="'%'+serial+'%'" />
serial like #{serial}

继续测试:

测试正常请求:http://127.0.0.1:6061/payment/getBySerial?serial=O

此时执行的SQL语句为:

请求结果:

测试SQL注入请求:http://127.0.0.1:6061/payment/getBySerial?serial=O" or 1=1 or "serial=O

此时执行的SQL语句为:

结果如下:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

睡竹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值