mybatis 防止sql注入的注意事项

1.sql注入的原理

     在页面参数输入时,输入有语法含义的字符串,这样可以改变你原有的SQL。

例如:

  1. <?php    
  2. $username = "aaa";    
  3. $pwd = "pwd";    
  4. $sql = "SELECT * FROM table WHERE username = '{$username}' AND pwd = '{$pwd}'";    
  5. echo $sql; //输出  SELECT * FROM table WHERE username = 'aaa' AND pwd = 'pwd'    
  6. ?>   

恶意用户 在不知道密码的情况下,通过or关键字来sql注入。

  1. <?php    
  2. $username = "aaa";    
  3. $pwd = "fdsafda' or '1'='1";  //前面的密码是瞎填的..后来用or关键字..意思就是无所谓密码什么都执行    
  4. $sql = "SELECT * FROM table WHERE username = '{$username}' AND pwd = '{$pwd}'";    
  5. echo $sql;  //输出  SELECT * FROM table WHERE username = 'aaa' AND pwd = 'fdsafda' or '1'='1'    
  6. ?>   

2.防止sql的原理

将sql语句的执行分成两部分

   第一步:先将不带参数的sql进行发给数据库进行预编译。

   第二步:将参数和预编译好的sql发给数据库执行。

                因为:sql注入只会影响到,sql预编译阶段,执行时就不管参数中的语法关键字了。

     注意:MyBatis是如何做到SQL预编译的呢?其实在框架底层,是JDBC中的PreparedStatement类在起作用,PreparedStatement是我们很熟悉的Statement的子类,它的对象包含了编译好的SQL语句。这种“准备好”的方式不仅能提高安全性,而且在多次执行同一个SQL时,能够提高效率。原因是SQL已编译好,再次执行时无需再编译。

例如:

<select id="getBlogById" resultType="Blog" parameterType=”int”>

         SELECT id,title,author,content

         FROM blog

WHERE id=#{id}

</select>

 

这里,parameterType表示了输入的参数类型,resultType表示了输出的参数类型。回应上文,如果我们想防止SQL注入,理所当然地要在输入参数上下功夫。上面代码中黄色高亮即输入参数在SQL中拼接的部分,传入参数后,打印出执行的SQL语句,会看到SQL是这样的:

SELECT id,title,author,content FROM blog WHERE id = ?

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


但是要注意一个细节

#{}:相当于JDBC中的PreparedStatement

${}:是输出变量的值,没有防止sql注入,需要自己通过技术手段过滤参数来防止sql注入。

例如:同样的sql语句只要把 #{id} 变成 ${id}就不能防止sql注入了。

<select id="getBlogById" resultType="Blog" parameterType=”int”>

         SELECT id,title,author,content

         FROM blog

WHERE id=${id}

</select>

打印出执行的SQL语句,会看到SQL是这样的:

SELECT id,title,author,content FROM blog WHERE id = 3

  参数和语句一起编译的不能,没有采用jdbc的参数绑定方式。



猜你喜欢

转载自blog.csdn.net/oLiHongMing/article/details/80014258