MyBatis-Plus自定义sql注入器

一、前言

在日常开发过程中,我们可能会发现 MyBatis-Plus 提供的那些自带的 sql 语句无法满足我们的开发需求,想要加一些自定义的 sql,而且要应用于所有的 Mapper 上,需要怎么实现呢?

二、MyBatis-Plus自定义sql注入器功能实现

官方文档地址:https://baomidou.com/pages/42ea4a/

2.1、编写自定义sql类

编写一个自定义 sql 类,要继承 AbstractMethod 类,然后实现其 injectMappedStatement 方法来定义 sql 语句并加入到 MappedStatement 里,也可以重写 getMethod 方法来修改方法名。

ps:这里以 LogicDeleteByIdWithFill (逻辑删除并做自动填充)举例,这个是 MyBatis-Plus 自己做的扩展,如果需要自己定义 sql,仿照这个或者DefaultSqlInjector 类里的各个默认方法写就可以了。

image-20230726144224910

其实如果自己在 xml 里写 sql 的话,最终也是添加到 MappedStatement 里,这里其实就是模拟了这个操作,而且每个 Mapper 都会走这段代码,看似每个 Mapper 的 xml 里没有这些方法,但其实都存在。

2.2、将自定义sql添加到BaseMapper中

这里建议写一个自己的 BaseMapper 继承自 MyBatis-Plus 的 BaseMapper,然后所有的业务 Mapper 都继承自己的 BaseMapper

public interface MyBaseMapper<T> extends BaseMapper<T> {

    /**
     * 带自动填充的删除
     *
     * @param entity
     * @return
     */
    int deleteByIdWithFill(T entity);
}

注意,这里的方法名要与2.1中 getMethod 方法返回的方法名一致。

2.3、编写自己的sql注入器

编写一个自己的 sql 注入器,继承 DefaultSqlInjector ,实现其 getMethodList 方法,将之前写的自定义 sql 类加入其中

@Component
public class MySqlInjector extends DefaultSqlInjector {

    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
        List<AbstractMethod> methodList = super.getMethodList(mapperClass);
        methodList.add(new LogicDeleteByIdWithFill());
        return methodList;
    }
}

这样就会在原本的方法基础上增加我们自定义的这个方法。

### MyBatis-Plus 中防止 Like 查询 SQL 注入的最佳实践 在开发过程中,SQL 注入是一个常见的安全威胁。对于像 `LIKE` 这样的查询操作,如果参数未经过适当处理,则可能成为攻击者利用的漏洞。以下是关于如何在 MyBatis-Plus 中有效预防和处理 `LIKE` 查询中的 SQL 注入问题的方法。 #### 使用预编译语句 MyBatisMyBatis-Plus 提供了内置的支持来通过预编译语句(PreparedStatement)自动转义特殊字符,从而减少手动编码的工作量并增强安全性。当使用动态 SQL 或条件构建器时,框架会自动生成带有占位符 (`?`) 的 SQL 语句[^1]。这可以确保传入的数据不会被解释为 SQL 片段的一部分。 ```java @Mapper public interface UserMapper extends BaseMapper<User> { @Select("SELECT * FROM user WHERE name LIKE CONCAT('%', #{name}, '%')") List<User> selectByNameLike(@Param("name") String name); } ``` 上述代码片段展示了如何通过 `#{}` 占位符绑定变量到 SQL 参数中,而不是直接拼接字符串。这种方式能够显著降低注入风险[^2]。 #### 利用 Wrapper 条件构造工具 MyBatis-Plus 提供了一个强大的 API——Wrapper 接口及其子接口 QueryWrapper 和 UpdateWrapper,用于简化复杂的查询逻辑编过程。这些工具可以帮助开发者更方便地实现模糊匹配功能的同时也提供了更高的安全保障: ```java QueryWrapper<User> wrapper = new QueryWrapper<>(); wrapper.like("name", userInput).or().like("email", userInput); List<User> users = userMapper.selectList(wrapper); ``` 这里的关键在于,无论何时调用了诸如 `.like()` 方法,内部都会采用安全的方式传递数据给数据库引擎执行[^3]。 #### 手动清理输入 尽管现代 ORM 已经极大地减少了手原始 SQL 的需求,但在某些情况下仍然不可避免要这样做。此时就需要特别注意对用户提交的内容进行额外验证与过滤。可以通过 Java 自带或者第三方库完成这一任务,比如 Apache Commons Lang 库下的 `StringEscapeUtils.escapeSql()` 函数[^4]: ```java import org.apache.commons.text.StringEscapeUtils; // 假设这是来自用户的不可信输入 String unsafeInput = request.getParameter("search"); // 转义潜在危险字符 String safeSearchTerm = "%" + StringEscapeUtils.escapeSql(unsafeInput) + "%"; ``` 不过需要注意的是,在大多数场景下推荐优先考虑前面提到的技术手段而非依赖于这种显式的转换方法,因为后者容易遗漏边界情况而导致隐患残留。 #### 配置全局拦截器 为了进一步加强防护措施,还可以定义一个通用的插件层用来捕获所有的请求并对其中涉及敏感字段的部分实施统一校验策略。例如创建一个基于 AspectJ AOP 的切面程序专门针对所有 DAO 层的操作加以审查[^5]。 --- ### 总结 综上所述,最佳实践中应尽可能依靠框架本身的能力去规避风险源;同时也要养成良好的编程习惯,如严格限定外部交互界面可接受的形式范围以及定期复查现有业务是否存在薄弱环节等问题所在之处。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

每天进步亿点点的小码农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值