【SQL注入】mybatis解决SQL注入的方案
背景
mybatis 好用,但有时候传参不免要用到 ${item} 的写法,比如要查询一个大表的某一些字段(由参数传入),或者按某字段进行排序,聚合等(这些字段由参数传入,并不是参数值)。这种时候,就会喜提一个SQL注入风险。
那这些场景不可避免,又是怎样去解决这些问题呢?
解决方案
要调整的地方有:
- mapper.java (在对应方法上,添加 @SelectProvider 注解)
- mapper.xml
- 创建一个 XXXProvider 类
1、改造mapper.java
// 原来写法
Map<String,Map<String,Object>> queryStu(StuDto stuDto);
// 后来写法
@SelectProvider(method = "queryStu", type = StuSelectProvider.class)
Map<String,Map<String,Object>> queryStu(StuDto stuDto);
就是添加了这一行,其它不变
@SelectProvider(method = "queryStu", type = StuSelectProvider.class)
其中 type 是新创建的,上面定义要拼装 sql 的方法, method 方法名,和 mapper 方法名一致就行
2、修改 mapper.xml
mapper.xml 文件的修改,就是把这个方法在 xml 文件里面的实现删掉就行,不然好像会冲突。
3、创建一个 StuSelectProvider.java
这个类名,对应 mapper 类的类名即可。
详情如下:
import org.apache.ibatis.jdbc.SQL;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import java.util.List;
public class StuSelectProvider {
public String queryStu(Dto dto) {
SQL sql = new SQL();
List<String> queryFields = dto.getQueryFields();
Assert.notEmpty(queryFields, "查询的列不能为空");
sql.SELECT(queryFields.toArray(new String[0]));
sql.FROM("tb_student");
sql.WHERE("name = #{name}");
sql.ORDER_BY("age desc");
sql.LIMIT(10);
return sql.toString();
}
}
意思是这个意思了。
动态列查询,直接在 xml 里面写,会SQL注入。
但使用 @SelectProvider 就可以实现,把 sql 拼装好,再给 mybatis 执行。好像就不会被扫描到。