【MyBatis】防止sql注入

前言

关于sql注入的解释这里不再赘述。 在MyBatis中防止的sql注入主要分为两种: 第一种就是MyBatis提供了两种支持动态 sql 的语法 #{} 和 ${},其中${} 是简单的字符串替换,而 #{} 在预处理时,会把参数部分用一个占位符 ? 代替,可以有效的防止sql的注入,面试的时候经常会问到,这里也不再详细赘述; 第二种是排序防止sql注入,实现方案如下

SQL注入过滤器

以下是sql注入过滤器,当判断出是非法字符时则抛出到自定义的异常类BusinessException中

public class SQLFilter {

    /**
     * SQL注入过滤
     *
     * @param sql 待验证字符串
     */
    public static String filterInject(String sql) {
        if (StringUtils.isBlank(sql)) {
            return null;
        }
        //去掉|"|;|字符
        sql = sql.replace("", "")
                .replace(""", "")
                .replace(";", "")
                .replace("\", "")
                .toLowerCase();
        //非法字符
        final String[] keywords = {"master", "truncate", "insert", "select", "delete", "update", "declare", "alert", "drop"};

        //判断是否包含非法字符
        for (String keyword : keywords) {
            if (sql.indexOf(keyword) > 0) {
                throw new BusinessException("SQL包含非法字符");
            }
        }
        return sql;
    }
}

分页工具类

这里我们使用的是PageHelper组件实现分页,需要在pom中引用jar包【com.github.pagehelper】

public class PageUtils {

    public static void initPaging(Map<String, Object> params) {
        //分页参数
        Object pageNumObj = params.get("page");
        Object pageSizeObj = params.get("limit");
        Object sortNameObj = params.get("sortName");
        Object sortOrderObj = params.get("sortOrder");
        //默认分页数为1
        int pageNum = pageNumObj != null ? Integer.parseInt(pageNumObj.toString()) : 1;
        //默认每页大小为10
        int pageSize = pageSizeObj != null ? Integer.parseInt(pageSizeObj.toString()) : 10;
        String orderBy = "";
        if (sortNameObj != null && sortOrderObj != null) {
            orderBy = sortNameObj.toString() + " " + sortOrderObj.toString();
        }
        PageHelper.startPage(pageNum, pageSize, SQLFilter.filterInject(orderBy));
    }

    public static Map<String, Object> filterParams(Map<String, Object> params) {
        Object sortNameObj = params.get("sortName");
        Object sortOrderObj = params.get("sortOrder");
        String orderBy = "";
        if (sortNameObj != null && sortOrderObj != null) {
            orderBy = sortNameObj.toString() + " " + sortOrderObj.toString();
        }
        params.put("orderBy",SQLFilter.filterInject(orderBy));
        return params;
    }


}

分页公共参数实体

@Data
public abstract class Query {

    // 初始分页页码
    private Integer page = 1;

    // 初始分页条数
    private Integer limit = 10;

    // 初始排序字段; sortName = "id"
    private String sortName;

    // 初始排序方式; sortOrder = "asc"
    private String sortOrder;
}

实现分页

实现方法中,【SysUserQuery 】中是我的业务逻辑中的查询参数,但是继承了分页公共参数实体,这里就不列出来了;

分页工具类中的方法由Map接收,由于我这里传的是实体,所以多出来一步实体转成Map操作;

@Override
    public Result queryPage(SysUserQuery sysUserQuery) {
        Map<String, Object> params = JSON.parseObject(JSON.toJSONString(sysUserQuery), Map.class);
        // 分页
        PageUtils.initPaging(params);
        // 查询数据
        List<SysUserVo> list = sysUserMapper.selectListByQuery(sysUserQuery);
        PageInfo page = new PageInfo(list);
        return new Result(page);
    }

至此结束。

经验分享 程序员 微信小程序 职场和发展