您好,登錄后才能下訂單哦!
這篇文章主要介紹了Mybatis是如何防止sql注入的,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
<select id="selectByNameAndPassword" parameterType="java.util.Map" resultMap="BaseResultMap"> select id, username, password, role from user where username = #{username,jdbcType=VARCHAR} and password = #{password,jdbcType=VARCHAR} </select>
<select id="selectByNameAndPassword" parameterType="java.util.Map" resultMap="BaseResultMap"> select id, username, password, role from user where username = ${username,jdbcType=VARCHAR} and password = ${password,jdbcType=VARCHAR} </select>
mybatis中的#和$的區(qū)別:
1、#將傳入的數(shù)據(jù)都當(dāng)成一個(gè)字符串,會(huì)對(duì)自動(dòng)傳入的數(shù)據(jù)加一個(gè)雙引號(hào)。
如:where username=#{username},如果傳入的值是111,那么解析成sql時(shí)的值為where username="111", 如果傳入的值是id,則解析成的sql為where username="id".
2、$將傳入的數(shù)據(jù)直接顯示生成在sql中。
如:where username=${username},如果傳入的值是111,那么解析成sql時(shí)的值為where username=111;
如果傳入的值是;drop table user;,則解析成的sql為:select id, username, password, role from user where username=;drop table user;
3、#方式能夠很大程度防止sql注入,$方式無(wú)法防止Sql注入。
4、$方式一般用于傳入數(shù)據(jù)庫(kù)對(duì)象,例如傳入表名.
5、一般能用#的就別用$,若不得不使用“${xxx}”這樣的參數(shù),要手工地做好過(guò)濾工作,來(lái)防止sql注入攻擊。
6、在MyBatis中,“${xxx}”這樣格式的參數(shù)會(huì)直接參與SQL編譯,從而不能避免注入攻擊。但涉及到動(dòng)態(tài)表名和列名時(shí),只能使用“${xxx}”這樣的參數(shù)格式。所以,這樣的參數(shù)需要我們?cè)诖a中手工進(jìn)行處理來(lái)防止注入。
【結(jié)論】在編寫MyBatis的映射語(yǔ)句時(shí),盡量采用“#{xxx}”這樣的格式。若不得不使用“${xxx}”這樣的參數(shù),要手工地做好過(guò)濾工作,來(lái)防止SQL注入攻擊。
sql注入解釋:是一種代碼注入技術(shù),用于攻擊數(shù)據(jù)驅(qū)動(dòng)的應(yīng)用,惡意的SQL語(yǔ)句被插入到執(zhí)行的實(shí)體字段中(例如,為了轉(zhuǎn)儲(chǔ)數(shù)據(jù)庫(kù)內(nèi)容給攻擊者)
SQL注入,大家都不陌生,是一種常見的攻擊方式。攻擊者在界面的表單信息或URL上輸入一些奇怪的SQL片段(例如“or ‘1'='1'”這樣的語(yǔ)句),有可能入侵參數(shù)檢驗(yàn)不足的應(yīng)用程序。所以,在我們的應(yīng)用中需要做一些工作,來(lái)防備這樣的攻擊方式。在一些安全性要求很高的應(yīng)用中(比如銀行軟件),經(jīng)常使用將SQL語(yǔ)句全部替換為存儲(chǔ)過(guò)程這樣的方式,來(lái)防止SQL注入
。這當(dāng)然是一種很安全的方式,但我們平時(shí)開發(fā)中,可能不需要這種死板的方式。
MyBatis框架作為一款半自動(dòng)化的持久層框架,其SQL語(yǔ)句都要我們自己手動(dòng)編寫,這個(gè)時(shí)候當(dāng)然需要防止SQL注入。其實(shí),MyBatis的SQL是一個(gè)具有“輸入+輸出”的功能,類似于函數(shù)的結(jié)構(gòu),參考上面的兩個(gè)例子。其中,parameterType表示了輸入的參數(shù)類型,resultType表示了輸出的參數(shù)類型。回應(yīng)上文,如果我們想防止SQL注入,理所當(dāng)然地要在輸入?yún)?shù)上下功夫。上面代碼中使用#的即輸入?yún)?shù)在SQL中拼接的部分,傳入?yún)?shù)后,打印出執(zhí)行的SQL語(yǔ)句,會(huì)看到SQL是這樣的:
select id, username, password, role from user where username=? and password=?
不管輸入什么參數(shù),打印出的SQL都是這樣的。這是因?yàn)镸yBatis啟用了預(yù)編譯功能,在SQL執(zhí)行前,會(huì)先將上面的SQL發(fā)送給數(shù)據(jù)庫(kù)進(jìn)行編譯;執(zhí)行時(shí),直接使用編譯好的SQL,替換占位符“?”就可以了。因?yàn)镾QL注入只能對(duì)編譯過(guò)程起作用,所以這樣的方式就很好地避免了SQL注入的問(wèn)題。
【底層實(shí)現(xiàn)原理】MyBatis是如何做到SQL預(yù)編譯的呢?其實(shí)在框架底層,是JDBC中的PreparedStatement類在起作用,PreparedStatement是我們很熟悉的Statement的子類,它的對(duì)象包含了編譯好的SQL語(yǔ)句。這種“準(zhǔn)備好”的方式不僅能提高安全性,而且在多次執(zhí)行同一個(gè)SQL時(shí),能夠提高效率。原因是SQL已編譯好,再次執(zhí)行時(shí)無(wú)需再編譯。
//安全的,預(yù)編譯了的 Connection conn = getConn();//獲得連接 String sql = "select id, username, password, role from user where id=?"; //執(zhí)行sql前會(huì)預(yù)編譯號(hào)該條語(yǔ)句 PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setString(1, id); ResultSet rs=pstmt.executeUpdate(); ......
//不安全的,沒(méi)進(jìn)行預(yù)編譯 private String getNameByUserId(String userId) { Connection conn = getConn();//獲得連接 String sql = "select id,username,password,role from user where id=" + id; //當(dāng)id參數(shù)為"3;drop table user;"時(shí),執(zhí)行的sql語(yǔ)句如下: //select id,username,password,role from user where id=3; drop table user; PreparedStatement pstmt = conn.prepareStatement(sql); ResultSet rs=pstmt.executeUpdate(); ...... }
【 結(jié)論:】
#{}:相當(dāng)于JDBC中的PreparedStatement
${}:是輸出變量的值
簡(jiǎn)單說(shuō),#{}是經(jīng)過(guò)預(yù)編譯的,是安全的
;${}是未經(jīng)過(guò)預(yù)編譯的,僅僅是取變量的值,是非安全的,存在SQL注入
。
如果我們order by語(yǔ)句后用了${},那么不做任何處理的時(shí)候是存在SQL注入危險(xiǎn)的。你說(shuō)怎么防止,那我只能悲慘的告訴你,你得手動(dòng)處理過(guò)濾一下輸入的內(nèi)容。如判斷一下輸入的參數(shù)的長(zhǎng)度是否正常(注入語(yǔ)句一般很長(zhǎng)),更精確的過(guò)濾則可以查詢一下輸入的參數(shù)是否在預(yù)期的參數(shù)集合中。
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“Mybatis是如何防止sql注入的”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來(lái)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。