今天突然在想大家一直说的sql注入是很危险的情况,那么mybatis是如何防止sql注入的呢?
带着这个疑问开始了搜索,最后探究如下:
原来mybatis在写sql的时候使用了#{},起到了预编译的效果,而这个预编译示例如下:
select name, age from table where school=#{school}
转变为如下
select name, age from table where school=?
就是将我们的参数预编译成一个占位符,这样mysql在执行的时候将占位符当成一个参数,这样即使写了可能sql注入的语句,mysql也会认为它只是一长串的参数,并不会当做sql语句执行,这样就防止了sql注入
示例:如school参数传入进来的是 【'hfut' or 1=1】 使用${}则会将全部数据查出来,而使用#{}则一条也查不出来,因为没有学校的名字是 'hfut' or 1=1,它把'hfut' or 1=1当成一整个参数
但是当使用${}的方式的时候,则是直接将参数值放入,然后预编译,这样很可能出现sql注入,因此在使用mybatis的时候能使用#{}就用,如果不行,比如涉及到动态表名和列名时,只能使用“${xxx}”这样的参数格式的时候,我们必须在代码层面进行校验判别,来防止sql注入的发生!
比如说表名或者order by的字段必须使用${},因为这些是不支持预编译后放入的,这是基本sql语句需要的,换句话说就是预编译后我们空出来的是参数,而#{}就是放入这些参数的
因此在此处也理解了预编译的作用了:将sql语句编译出来,只留下参数占位符,这样的好处1是防止sql注入,好处2是如果需要多次查询,sql骨架不变的化,性能也会大大提升。