1. 程式人生 > 實用技巧 >mybatis防止sql注入

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注入攻擊。