Mybatis的#{}佔位符與${}字符串替換的區別

1、#{}是預編譯處理,$ {}是字符串替換

(1)#{} 表示一個佔位符,採用preparedStatement給佔位符設置值,自動進行java類型和jdbc類型轉換,進行預編譯處理,#{}可以有效防止sql注入(預編譯是提前對SQL語句進行編譯,而其後注入的參數將不會再進行編譯)

(2)${} 表示字符串替換,通過${}可以將parameterType或實體 傳入的內容拼接在sql中且不進行jdbc類型轉換

(3)舉例說明二者區別,現在有如下SQL:

select count(1) from user where user_name = #{userName} and password = #{password}

使用#{}時,會進行jdbc類型轉換,根據屬性 自動加上單引號

select count(1) from user where user_name = 'admin' and password = '123456';

而${}不會進行jdbc類型轉換,只是簡單的替換, 顯然有語法錯誤,但是可以利用其進行sql注入

select count(1) from user where user_name = admin and password = 123456;

2、SQL注入舉例離說明

SQL注入就是利用現有應用程序,將(惡意)的SQL命令注入到後臺數據庫執行一些惡意的操作。比如說,在登錄過程中,利用上面的語句到數據庫中查找用戶名/密碼是否存在,如果存在就登錄成功,如果不存在就登錄失敗。

若使用${},惡意用戶在表單中的用戶名文本框中輸入的是'admin',密碼框中輸入的是 ' ' or 1 = 1 加了一引號和一個恆成立的條件,那麼,傳到數據庫中的sql就是:

select count(1) from user where user_name = 'admin' and user_password = ' ' or 1=1

登錄成功,該惡意用戶是可以登錄系統的! 這就是SQL注入,惡意攻擊

而如果使用#{}是不會出現這種情況的,#{}默認會給輸入的值加上引號,密碼錯誤,登錄失敗

select count(1) from user where user_name = ''admin'' and user_password ='' ' or 1=1'

3、既然有了#{}爲什麼還需要${}

#{}並不適用一些其他場景,比如要根據參數名動態排序,需要傳入的參數是字段名,使用#{} 被解析成order by 'age' ,顯然達不到排序目的。而此時就用到了${}進行字符串替換操作,即sql解析成 order by age

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章