针对web安全问题,需要将项目中mybatis涉及${}的代码全部改成#{},由于涉及$的代码多是in和like,现在提供以下解决思路
针对name like ‘%${name}%’ 这样的模式查询 使用sql内建函数 instr(str, substr[, position[, occurrence]])替代
str:源字符substr:目标字符position:初始索引occurrence:出现次数 instr(name, #{name,jdbcType=VARCHAR})>0 替代 name like '%${name}%'使用instr的优势在于,当数据量很多时instr的效率比like要高(索引对instr有效)
注意:此方式只能出来like模糊查询的sql注入问题
针对id in (${ids})这样条件查询中插入的语句,在代码中对参数进行校验
/** * Created by white_while * @author white_while */ public class CheckSqlParam { private CheckSqlParam() {} public static boolean checkParam(Map<Object, Object> paramMap, Set<String> ids) { boolean outcome = true; // 校验一下数据库类型为int的参数是否存在sql注入的风险 Map<String, Object> result = new HashMap<String, Object>(){{ put("param", null); }}; try { paramMap.entrySet().stream().forEach(entry -> { boolean flag = ids.contains(entry.getKey()); if (flag) { result.put("param", entry); String str = (String) entry.getValue(); // 将参数强转为int,若报错则传入参数有误 Arrays.stream(str.split(",")).forEach(Integer::parseInt); } }); } catch (NumberFormatException e) { outcome = false; } return outcome; } }调用方:
public Result getPojosOnCondition(Map<Object, Object> pojoMap) { // 校验一下参数是否存在sql注入的风险 // ids applicationId userIds Set<String> ids = new HashSet<String>(Arrays.asList("ids", "applicationId", "userIds")); boolean outcome = CheckSqlParam.checkParam(pojoMap, ids); if (!outcome) { return new Result("参数有误"); } ... }注意:此方式只能处理用于in的数据库类型为int的参数
