1. 程式人生 > >MyBatis Tips:#與$的區別

MyBatis Tips:#與$的區別

最近開發的時候遇到了一些問題,我在做一個Oracle轉SQL Server的專案時,遇到了MyBatis中對於SQL語句轉義的疑惑,經過學習,整理如下。

1,MyBatis中的 # 與 $ 的區別

其實,區別就是如果使用#{}#,會將{}裡面的傳入的值自動解析成為帶引號的值,比如:

select count(1) from t_user where user_name = #{userName} and user_pwd = #{userPassword}

假如,此時傳入user_name傳入的值為admin,user_pwd傳入的值為123456,那麼最後的SQL就是:

select count(1) from t_user where user_name = 'admin' and user_pwd = '123456';

會解析成字串,而${}就會這樣解析:

select count(1) from t_user where user_name = admin and user_pwd = 123456;

這個SQL語句在SQL Server中是可行的,然而到了Oracle就變成了錯誤語句,此為第一處區別。另外#{}可以有效的防止SQL注入,那麼什麼是SQL注入呢?

2,什麼是SQL注入?

SQL注入就是利用現有應用程式,將(惡意)的SQL命令注入到後臺資料庫執行一些惡意的操作

比如說,在登入過程中,利用上面的語句到資料庫中查詢使用者名稱/密碼是否存在,如果存在就登入成功

而如果不存在就登入失敗,如果說你後臺使用的是${},惡意使用者在表單中的使用者名稱文字框中輸入的是’admin’

密碼框中輸入的是’ ’ or 1 = 1 加了一引號和一個恆成立的條件,那麼,傳到資料庫中的SQL就是:

select count(1) from t_user where user_name = 'admin' and user_pwd = ' ' or 1=1

如果程式沒有做其他的校驗,此時,該惡意使用者是可以登入系統的。 這就是SQL注入,惡意攻擊

而使用#{}是不會出現這種情況的,#{}預設會給輸入的值加上引號,這樣轉義之後的SQL語句就是:

select count(1) from SSB_USER where user_name = 'admin' and user_pwd = ''' or 1=1'

但是使用#{}在動態場景下並不適用,比如要使用到排序 order by #{} 傳入的引數應是表對應欄位名,但是加上引號後就會解析成 order by ‘xxx’

這樣就達不到排序的目的,而此時如果使用${}就可以達到排序的目的,即,SQL解析成 order by xxx,根據xxx排序。