首先我们要知道mybatis中使用jdbc连接数据库的时候使用的是preparedStatement还是statement?
这里说明一下,如果我们在mapper文件中的sql语句中写的是$
进行参数传递那么它就会拼接成字符串,然会执行,实际上使用的就是statement,但是如果我们用#
进行参数传递,他使用的就是preparedStatement,可以防止sql注入。
那么我们不就全都用#
不就行了吗?
下面我们就研究一下他们俩的区别,也就是能用$
而不能使用#
的地方。
在mybatis中,”${xxx}”这样格式的参数会直接参与sql编译,从而不能避免注入攻击。但涉及到动态表名和列名时,只能使用“${xxx}”这样的参数格式,所以,这样的参数需要我们在代码中手工进行处理来防止注入。
实验:
使用预编译的数据库操作对象进行注入值的时候,列名是不能够被写入的。你看上面我们让它降序排列但是并没有。
所以在mybatis中的$
符号可以直接替换掉列明,这就是能够用$
二不能用#
的地方。
那么这种情况下如何避免sql注入呢?
实验:
我们数据库中的数据:
<select id="getAllUserLike" resultType="com.dongmu.pojo.User">
select * from User where name like "%"#{param}
</select>
测试代码:
@org.junit.Test
public void test04(){
SqlSession session = MybatisUtil.getSession();
UserDao mapper = session.getMapper(UserDao.class);
List<User> users = new ArrayList<>();
users=mapper.getAllUserLike("i");
session.close();
for (User user : users) {
System.out.println(user);
}
}
查询结果
User{id=1, name='lisi', pwd='123'}
User{id=7, name='husi', pwd='222'}
User{id=8, name='kiki', pwd='000'}
因为有的场合必须用$
,我们把%
改成$
<select id="getAllUserLike" resultType="com.dongmu.pojo.User">
select * from User where name like '%${param}'
</select>
附上代码:
@org.junit.Test
public void test04(){
SqlSession session = MybatisUtil.getSession();
UserDao mapper = session.getMapper(UserDao.class);
List<User> users = new ArrayList<>();
users=mapper.getAllUserLike("i' or '1'='1");
// users=mapper.getAllUserLike("i");
session.close();
for (User user : users) {
System.out.println(user);
}
}
看到sql注入了吧,所以在编写mybatis的映射语句时,尽量采用“#{xxx}”这样的格式。若不得不使用“${xxx}”这样的参数,要手工地做好过滤工作,来防止sql注入攻击。
版权声明:本文为qq_45401910原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。