最近修改項目中sql注入問題,4位數以上的接口須要手動修改,改的想吐,前來吐槽一波前端
舉個栗子:java
好比登陸接口定義若是以下定義:mysql
<select id="UserLogin" parameterType="hashmap" resultType="java.util.HashMap"> SELECT U.USER_CODE, USER_NAME, USER_PASS, USER_TYPE, USER_STA, OPEN_DATE FROM UUM_USER U WHERE U.USER_CODE = '${USER_CODE}' AND USER_PASS = '${USER_PASS}' </select>
對於oracle數據庫,在前端登陸頁面用戶名只須要輸入 admin' --,密碼隨便輸入,那麼執行的sql語句就是「SELECT U.USER_CODE,USER_NAME,USER_PASS,USER_TYPE,USER_STA,OPEN_DATEFROM UUM_USER UWHERE U.USER_CODE = 'admin' --'AND USER_PASS = 'XXXXXXXXX'」,很明顯密碼驗證語句被註釋掉了,那麼咱們就可隨意在不須要密碼的狀況下登陸任意用戶的帳號了,mysql只須要把--換成#就好了這樣就是經過SQL注入來作壞事了sql
解決方法:數據庫
1,對於上述'${user_code}'的寫法咱們須要換成#{user_code},#{}的寫法執行sql前會進行預編譯,參數部分會先使用佔位符?來參與預編譯,而後在進行參數賦值,這樣的玩法是安全的數組
<select id="UserLogin" parameterType="hashmap" resultType="java.util.HashMap"> SELECT U.USER_CODE, USER_NAME, USER_PASS, USER_TYPE, USER_STA, OPEN_DATE FROM UUM_USER U WHERE U.USER_CODE = #{USER_CODE} AND USER_PASS = #{USER_PASS} </select>
2,對於有LIKE語句的,直接換成#寫法會致使語句編譯不經過,須要使用concat(concat('%',#{user_code}),'%'))替換'%${user_code}%'安全
3,對於有order by '${user_code}'比較麻煩,要麼對入參進行提早過濾,要麼換用存儲過程來替換接口mybatis
4,對於IN( '${user_code}')也不能直接替換,由於替換爲#{user_code},oracle會把數組識別爲一個字符串,解決方法:oracle
使用mybatis中的foreach語句來修改: <foreach collection="list" item="item" open="("separator="," close=")">#{user_code}</foreach>spa
a. 若是傳入的是單參數且參數類型是一個List的時候,collection屬性值爲list b. 若是傳入的是單參數且參數類型是一個array數組的時候,collection的屬性值爲array c. 若是傳入的參數是多個的時候,咱們就須要把它們封裝成一個Map了,collection的屬性值爲對應key值