Mybatis 中#和$的區別
-
${}是 Properties 檔案中的變數佔位符,它可以用於標籤屬性值和 sql 內部,屬於靜態文字替換
-
‘#{}’是 sql 的引數佔位符,Mybatis 會將 sql 中的#{}替換為?號,在 sql 執行前會使用PreparedStatement 的引數設定方法,按序給 sql 的? 號佔位符設定引數值。
-
‘#’方式能夠很大程度防止 sql 注入。
\(方式無法防止 Sql 注入。 \)方式一般用於傳入資料庫物件,例如傳入表名。 -
為什麼 # 可以防止SQL注入?參考作者:https://www.cnblogs.com/coder-who/
-
1.什麼是SQL注入
答:SQL注入是通過把SQL命令插入到web表單提交或通過頁面請求的查詢字串,最終達到欺騙伺服器執行惡意的SQL指令。
注入攻擊的本質是把使用者輸入的資料當做程式碼執行。
舉例如: 表單有兩個使用者需要填寫的表單資料,使用者名稱和密碼,如果使用者輸入admin(使用者名稱),111(密碼),若資料庫中存在此使用者則登入成功。SQL大概是這樣
SELECT * FROM XXX WHERE userName = admin and password = 111
但若是遭到了SQL注入,輸入的資料變為 admin or 1 =1 # 密碼隨便輸入,這時候就直接登入了,SQL大概是這樣
SELECT * FROM XXX WHERE userName = admin or 1 = 1 # and password = 111 ,因為 # 在sql語句中是註釋,將後面密碼的驗證去掉了,而前面的條件中1 = 1始終成立,所以不管密碼正確與否,都能登入成功。
2.mybatis中的#{} 為什麼能防止sql注入,${}不能防止sql注入
答: #{}在mybatis中的底層是運用了PreparedStatement 預編譯,傳入的引數會以 ? 形式顯示,因為sql的輸入只有在sql編譯的時候起作用,當sql預編譯完後,傳入的引數就僅僅是引數,不會參與sql語句的生成,而${}則沒有使用預編譯,傳入的引數直接和sql進行拼接,由此會產生sql注入的漏洞。
-
再次理解sql預編譯前後傳引數的區別?參考作者:https://blog.csdn.net/weixin_46099269
- select * from user where uid=#{id} and password=#{pwd};
這時資料庫就會進行預編譯,並進行一個快取動作,快取一條這樣的語句:
select * from user where uid=? and password=?;
當我們呼叫這條語句,並實際向#{id}中的id傳了一個值 “deftiii” or 1=1# 時,不需要在編譯,資料庫會直接找對應的表中有沒有名字是 “deftiii” or 1=1# 的使用者,而不再有編譯sql語句的過程。
- select * from user where uid=#{id} and password=#{pwd};
-