mybatis--#{}與${}的區別

首先,談談mybatis怎麼防止sql注入sql

<select id="selectUserInfo" resultType="com.test.vo.User" parameterType=」int」>
		SELECT
			tu.USER_ID as userId,
			tu.USER_NAME as userName
		FROM
			t_user tu
		WHERE
			tu.USER_ID = #{userId}
	</select>

上述是mybatis的mapping中一段代碼,當請求的時候,控制檯輸出數據庫

SELECT tu.USER_ID,tu.USER_NAME FROM t_user tu WHERE tu.USER_ID = ?

咱們會發現,不管輸入什麼參數,打印出的sql都是這樣。緣由是:
mybatis啓用了預編譯功能,在SQL執行前,會將上面的sql發送給數據庫進行編譯;執行SQL的時候,直接使用預編譯好的sql,傳參替換佔位符"?"就行。由於sql注入只能對編譯過程起做用,所以,這種方式能夠很好地避免sql注入問題。
mybatis底層實現原理
mybatis如何作到sql預編譯?在底層框架的JDBC中的preparedStatement類起做用,該類的對象包含了許多編譯好的SQL語句,這種預先編譯的方式不只能提升安全性,並且在屢次執行同一個SQL的時候,可以提升效率,由於已經編譯好的SQL,不須要再次編譯了。
如今假設mybatis的mapping中的傳參以下安全

WHERE
			tu.USER_ID = ${userId}

執行請求時,假設傳參1000000000,打印出來的SQL是這樣的mybatis

SELECT tu.USER_ID,tu.USER_NAME FROM t_user tu WHERE tu.USER_ID = 1000000000

結果發現傳參直接顯示出來,這樣是沒法阻止SQL注入的,在mybatis中,${xx}這種格式的參數是直接參與SQL編譯,從而不能避免注入攻擊。可是涉及到動態表名與列名時,只能使用${xx}這種格式參數。
總結:在編寫mybatis映射語句時,儘可能採用#{xx}這樣的格式。簡單的理解#{}是通過預編譯的,是安全的;而${}是直接編譯,不安全的。
如今假設必須使用${}這種方式,則咱們須要手動的過濾一下內容(好比正則匹配等)。app

相關文章
相關標籤/搜索