【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 执行。好像就不会被扫描到。

posted @ 2023-02-20 14:29  aaacarrot  阅读(1679)  评论(0编辑  收藏  举报