一篇文章弄懂Mybatis中#和$的區別

前言

在學校的時候,想必大傢肯定聽老師講過,在mybatis中,配置參數要用#,不要用$符號。因為$不安全,容易被sql註入。講是這麼講,但是如何註入的,大傢一起來看看吧。

一:下面我們寫個關於“#”的個sql,看能不能註入。

 <select id="selectUser" resultMap="BaseResultMap">
    SELECT 
    	acc.user_name FROM dfws_sys_user_account AS acc
    WHERE
        acc.user_name like #{userName}
  </select>

1.正常傳參

DfwsSysUserAccount user = new DfwsSysUserAccount();
user.setUserName("wanglingzhi");
List<DfwsSysUserAccount> list = userAccountService.selectUser(user);
if(list!=null && list.size()>0){
    for (DfwsSysUserAccount u:list) {
    	System.out.println("用戶名:"+u.getUserName());
    }
}else{
        System.out.println("暫無數據");
}

sql打印:

Preparing: SELECT acc.user_name FROM dfws_sys_user_account AS acc WHERE acc.user_name = ? 

Parameters: wanglingzhi(String)

2.拼接傳參

DfwsSysUserAccount user = new DfwsSysUserAccount();
user.setUserName("'wanglingzhi' or acc.user_name = 'shuizhong'");
List<DfwsSysUserAccount> list = userAccountService.selectUser(user);
if(list!=null && list.size()>0){
    for (DfwsSysUserAccount u:list) {
    	System.out.println("用戶名:"+u.getUserName());
    }
}else{
        System.out.println("暫無數據");
}

sql打印:

Preparing: SELECT acc.user_name FROM dfws_sys_user_account AS acc WHERE acc.user_name = ? 

Parameters: wanglingzhi or acc.user_name = shuizhong(String)

二:下面我們寫個關於“$”的個sql,看能不能註入。

<select id="selectUser" resultMap="BaseResultMap">
    SELECT 
    	acc.user_name FROM dfws_sys_user_account AS acc
    WHERE
        acc.user_name like ${userName}
  </select>

1.正常傳參

DfwsSysUserAccount user = new DfwsSysUserAccount();
user.setUserName("'wanglingzhi'");
List<DfwsSysUserAccount> list = userAccountService.selectUser(user);
if(list!=null && list.size()>0){
    for (DfwsSysUserAccount u:list) {
    	System.out.println("用戶名:"+u.getUserName());
    }
}else{
        System.out.println("暫無數據");
}

打印sql:

SELECT acc.user_name FROM dfws_sys_user_account AS acc WHERE acc.user_name = ‘wanglingzhi’

2.拼接傳參

DfwsSysUserAccount user = new DfwsSysUserAccount();
user.setUserName("'wanglingzhi' or acc.user_name = 'shuizhong'");
List<DfwsSysUserAccount> list = userAccountService.selectUser(user);
if(list!=null && list.size()>0){
    for (DfwsSysUserAccount u:list) {
    	System.out.println("用戶名:"+u.getUserName());
    }
}else{
        System.out.println("暫無數據");
}

打印sql:

SELECT acc.user_name FROM dfws_sys_user_account AS acc WHERE acc.user_name = ‘wanglingzhi’ or acc.user_name = ‘shuizhong’ 

很顯然,這裡已經sql註入瞭。

總結下,一般說來,二者的區別可總結為以下6點:

(1)#將傳入的數據都當成一個字符串,會對自動傳入的數據加一個雙引號。如:order by #user_id#,如果傳入的值是111,那麼解析成sql時的值為order by “111”,如果傳入的值是id,則解析成的sql為order by “id”。

(2)$將傳入的數據直接顯示生成在sql中。如:order by $user_id$,如果傳入的值是111,那麼解析成sql時的值為order by user_id, 如果傳入的值是id,則解析成的sql為order by id。

(3)#方式在很大程度上能夠防止sql註入。

(4)$方式無法防止sql註入。

(5)$方式一般用於傳入數據庫對象,例如傳入表名。

(6)一般能用#的就別用$。

ps:在使用mybatis中還遇到<![CDATA[]]>的用法,在該符號內的語句,將不會被當成字符串來處理,而是直接當成sql語句,比如要執行一個存儲過程。

總結

到此這篇關於Mybatis中#和$區別的文章就介紹到這瞭,更多相關Mybatis #和$區別內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: