MyBatis如何防止SQL注入

下面是MyBatis一个Dao配置mysql

<select id="findRank" parameterType ="String" resultType="String">
        SELECT u.name FROM UserInfo u
            where 1=1
            and u.UserID=#{userID} ; 
    </select>

打印出执行的SQL语句sql

SELECT u.name FROM UserInfo u where 1=1 and u.UserID=? 

这是由于MyBatis启用了预编译功能,在SQL执行前,会先将上面的SQL发送给数据库进行编译;执行时,直接使用编译好的SQL,替换占位符“?”就能够了。由于SQL注入只能对编译过程起做用,因此这样的方式就很好地避免了SQL注入的问题。
【底层实现原理】
MyBatis是如何作到SQL预编译的呢?其实在框架底层,是JDBC中的PreparedStatement类在起做用,PreparedStatement是咱们很熟悉的Statement的子类,它的对象包含了编译好的SQL语句。这种“准备好”的方式不只能提升安全性,并且在屡次执行同一个SQL时,可以提升效率。缘由是SQL已编译好,再次执行时无需再编译。数据库

话说回来,是否咱们使用MyBatis就必定能够防止SQL注入呢?固然不是,请看下面的代码:安全

<select id="findRank" parameterType ="String" resultType="String">
        SELECT u.name FROM UserInfo u
            where 1=1
            and u.UserID=${userID} ;   
    </select>

假设userID=1,将SQL打印出来是这样的:框架

SELECT u.name FROM UserInfo u where 1=1 and u.UserID=1

假如:
userID=1;drop table UserInfo ;那么sql是这样的测试

SELECT u.name FROM UserInfo u where 1=1 and u.UserID=1;drop table UserInfo ;
 测试结果

 SELECT u.name FROM UserInfo u where 1=1 and u.UserID=1;drop table UserInfo;
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'drop table UserInfo' at line 3 直接报异常,你应该庆幸mybaties作了处理,可是无论怎么说${xxx}是没法阻止SQL注入的。

${xxx}”
缺点: 直接参与SQL编译,不能避免注入攻击。
优势:及到动态表名和列名时,只能使用“${xxx}”这样的参数格式
注意: 这样的参数须要咱们在代码中手工进行处理来防止注入。ui

“#{xxx}“
至关于JDBC中的PreparedStatement
${}:是输出变量的值
优势:#{}是通过预编译的,是安全的;spa

相关文章
相关标签/搜索