国家林业建设工程协会网站整站排名优化品牌
文章目录
- 区别
- 详细讲解
- ${}sql注入案例
区别
#会进行预编译,安全,通过#{}传入的参数 mybatis会认为是一个字符串,自动加上引号“”
$ 不会进行预编译,通过$ 传入的参数会直接取出来使用,可能会产生sql注入风险,
只有当传入的是表名时必须用$传入
,其他的都建议用#{}传入
详细讲解
MyBatis中使用parameterType向SQL语句传参,parameterType支持的类型可以是基本类型int,String,HashMap和java自定义类型。
在SQL中引用这些参数的时候,可以使用两种方式:
#{parameterName}
${parameterName}
首先,我们说一下这两种引用参数时的区别,使用#{parameterName}引用参数的时候,Mybatis会把这个参数认为是一个字符串,并自动加上引号’ ',例如传入参数是“tom”,那么在下面SQL中:
Select * from user where name = #{name}
使用的时候就会转换为:
Select * from user where name = 'tom';
同时使用${parameterName}的时候在下面SQL中
Select * from user where name = ${name}
就会直接转换为:
Select * from user where name = tom
简单说#{}是经过预编译的,是安全的。
而${}是未经过预编译的,仅仅是取变量的值,是非安全的,存在SQL注入。
#{} 这种取值是编译好SQL语句再取值
${} 这种是取值以后再去编译SQL语句
${}sql注入案例
以下用一个示例来看一下$传参sql注入的问题
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.springboot.store.mapper.UserMapper"><select id="selectByUsername">select * from t_user where username = ${username}</select>
</mapper>
在单元测试中传入参数如下:
@Test
public void reg1(){userService.selectByUsername("tom or phone = 123");}
日志打印sql如下:
select * from t_user where username = tom or phone = 123
可以看到,我们只是想通过username字段查询,但是条件里面却被拼接了phone字段的条件。
接着我们把UserMapper.xml中的$替换为#
UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.springboot.store.mapper.UserMapper"><select id="selectByUsername">select * from t_user where username = ${username}</select>
</mapper>
日志打印sql如下:
select * from t_user where username = 'tom or phone = 123'
此时只会根据username条件进行查询。