mybatis防止sql注入

昨天面试官问到一个mybatis是如何预防sql注入的问题,当时脑子直接就想到:预编译,然后就GG

只是大概的知道mybatis会将我们写好的sql语句进行预编译,然后将传参进去的参数都看作是字符串类型,在传参这里卡住不出现异常的sql注入;

讲完之后觉得太水了,后面细化学习一下:

mybatis中的#和$的区别:

1、#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号;可以预防SQL注入

如:where username=#{username},如果传入的值是111,那么解析成sql时的值为where username="111", 如果传入的值是id,则解析成的sql为where username="id". 

2、$将传入的数据直接显示生成在sql中;不进行预编译,无法预防SQL注入,需要在代码中做处理

如:where username=${username},如果传入的值是111,那么解析成sql时的值为where username=111;如果是传入 or 1=1;这样子筛选条件失效了;

如果传入的值是;drop table user;,则解析成的sql为: where username=;drop table user; 删除数据表,导致

3、#方式能够很大程度防止sql注入,$方式无法防止Sql注入。

4、$方式一般用于传入数据库对象,例如传入表名.

5、一般能用#的就别用$,若不得不使用“${xxx}”这样的参数,要手工地做好过滤工作,来防止sql注入攻击。

6、在MyBatis中,“${xxx}”这样格式的参数会直接参与SQL编译,从而不能避免注入攻击。但涉及到动态表名和列名时,只能使用“${xxx}”这样的参数格式。所以,这样的参数需要我们在代码中手工进行处理来防止注入。

mybatis实现防止sql注入:

  MyBatis框架作为一款半自动化的持久层框架,其SQL语句都要我们自己手动编写,这个时候当然需要防止SQL注入。MyBatis的SQL是一个具有“输入+输出”的功能,类似于函数的结构。其中,parameterType表示了输入的参数类型,resultType表示了输出的参数类型。如果我们想防止SQL注入,要在输入参数上下功夫。上面代码中使用#的即输入参数在SQL中拼接的部分,传入参数后,打印出执行的SQL语句,会看到SQL是这样的:

select id, username, password, role from user where username=? and password=?

  不管输入什么参数,打印出的SQL都是这样的。这是因为MyBatis启用了预编译功能,在SQL执行前,会先将上面的SQL发送给数据库进行编译;执行时,直接使用编译好的SQL,替换占位符“?”就可以了。因为SQL注入只能对编译过程起作用,所以这样的方式就很好地避免了SQL注入的问题。

【结论】在编写MyBatis的映射语句时,尽量采用“#{xxx}”这样的格式。若不得不使用“${xxx}”这样的参数,要手工地做好过滤工作,来防止SQL注入攻击。

 

mybatis防止sql注入

上一篇:Oracle 数据泵(expdp/impdp)操作详解


下一篇:sql语句大全