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

相關文章
相關標籤/搜索