最近修改项目中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值