SQL注入,大家都不陌生,是一種常見的攻擊方式。攻擊者在界面的表單信息或URL上輸入一些奇怪的SQL片段(例如“or ‘1’=’1’”這樣的語句),有可能入侵參數檢驗不足的應用程序。所以,在我們的應用中需要做一些工作,來防備這樣的攻擊方式。在一些安全性要求很高的應用中(比如銀行軟件),經常使用將SQL語句全部替換為存儲過程這樣的方式,來防止SQL注入。這當然是一種很安全的方式,但我們平時開發中,可能不需要這種死板的方式。
1.${}模糊查詢存在SQL注入的例子:(${}未編譯,只是對其進行拼接,相當於Statement)
SQL:
<select id="getInfo2" resultType="cn.xm.exam.bean.haul.Haulinfo" parameterType="hashmap"> SELECT * FROM haulinfo <where> <if test="name != null"> and bigname like '%${name}%' </if> <if test="status != null"> and bigStatus = #{status} </if> </where> </select>
Java測試:
本來是模糊查詢名字,結果對描述添加了過濾。
@Test public void test2() throws SQLException { Map condition = new HashMap(); condition.put("name", "%' and bigdescription like '陽城"); condition.put("status", "未開始"); testMapper.getInfo2(condition); }
Preparing: SELECT * FROM haulinfo WHERE bigname like '%%' and bigdescription like '陽城%' and bigStatus = ?
Parameters: 未開始(String)
Total: 2
2. bind + #{} 模糊查詢 防止SQL注入 (#{}進行預編譯,傳遞的參數不進行編譯,只作為參數,相當於PreparedStatement)
bind 元素可以從 OGNL 表達式中創建一個變量並將其綁定到上下文。比如:
<select id="selectBlogsLike" resultType="Blog"> <bind name="pattern" value="'%' + _parameter.getTitle() + '%'" /> SELECT * FROM BLOG WHERE title LIKE #{pattern} </select>
例如SQL:
<select id="getInfo" resultType="cn.xm.exam.bean.haul.Haulinfo" parameterType="hashmap"> SELECT * FROM haulinfo <where> <if test="name != null"> <bind name="names" value="'%'+name+'%'" /> and bigname like #{names} </if> <if test="status != null"> and bigStatus = #{status} </if> </where> </select>
Java測試:
@Test public void test1() throws SQLException { Map condition = new HashMap(); condition.put("name", "%' and bigdescription like '陽城"); condition.put("status", "未開始"); testMapper.getInfo(condition); }
Preparing: SELECT * FROM haulinfo WHERE bigname like ? and bigStatus = ?
Parameters: %%' and bigdescription like '陽城%(String), 未開始(String)
Total: 0
3.另一種模糊查詢方法
select departmentid,updepartmentid,departmentname from
department where departmentid like concat(#{departmentid},'%')
<if test="documentName!=null && documentName!=''"> and documentName like concat(concat('%',#{documentName}),'%') </if>
【結論】在編寫MyBatis的映射語句時,盡量采用“#{xxx}”這樣的格式。若不得不使用“${xxx}”這樣的參數,要手工地做好過濾工作,來防止SQL注入攻擊。
#{}:相當於JDBC中的PreparedStatement
${}:是輸出變量的值
簡單說,#{}是經過預編譯的,是安全的;${}是未經過預編譯的,僅僅是取變量的值,是非安全的,存在SQL注入。
如果我們order by語句后用了${},那么不做任何處理的時候是存在SQL注入危險的。你說怎么防止,那我只能悲慘的告訴你,你得手動處理過濾一下輸入的內容。如判斷一下輸入的參數的長度是否正常(注入語句一般很長),更精確的過濾則可以查詢一下輸入的參數是否在預期的參數集合中。