1. 程式人生 > 其它 >Mybatis 中#和$的區別

Mybatis 中#和$的區別

  1. ${}是 Properties 檔案中的變數佔位符,它可以用於標籤屬性值和 sql 內部,屬於靜態文字替換

  2. ‘#{}’是 sql 的引數佔位符,Mybatis 會將 sql 中的#{}替換為?號,在 sql 執行前會使用PreparedStatement 的引數設定方法,按序給 sql 的? 號佔位符設定引數值。

  3. ‘#’方式能夠很大程度防止 sql 注入。
    \(方式無法防止 Sql 注入。 \)方式一般用於傳入資料庫物件,例如傳入表名。

  4. 為什麼 # 可以防止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語句的過程。