当前使用版本(必填,否则不予处理)

3.5.3.1

MyBatis-Plus BlockAttackInnerInterceptor bug

Comment From: refeccd

MyBatis-Plus BlockAttackInnerInterceptor bug 照目前这个逻辑来看,只要是某个字段不等于某个值的情况下,都会报错。麻烦尽快修复下

Comment From: widely5201

是的是的,我也碰到了这个问题

Comment From: timnick-snow

这应该是预期行为吧。防止全表删除。你这sql真执行下去,全表只剩下1条数据了~~太危险了吧

删除这种危险操作,为啥要用 ne 操作符。 更加安全的操作是根据id删除 removeBatchByIds , removeById

Comment From: refeccd

这应该是预期行为吧。防止全表删除。你这sql真执行下去,全表只剩下1条数据了~~太危险了吧

预期行为?麻烦仔细看看代码逻辑再说出来这个话

删除这种危险操作,为啥要用 ne 操作符。 更加安全的操作是根据id删除 removeBatchByIds , removeById

如果像你说的这样,那干脆直接删掉 not equal 相关的的方法好了

Comment From: refeccd

明显拦截器里没有考虑到,where 表达式左边是表字段的情况。 只是判断了下常量,左边是否不等于右边。 这难道不是一个明显的 bug 吗

Comment From: timnick-snow

明显拦截器里没有考虑到,where 表达式左边是表字段的情况。 只是判断了下常量,左边是否不等于右边。 这难道不是一个明显的 bug 吗

并不觉得是bug。这正是防止全表删除的价值。如果你一定要全表删除,为什么要注入这个插件。这个插件默认是不启用的。 如果你启用了,还是有大量删除的需求,你完全可以先用ne进行查询出id,然后再用removeBatchByIds进行删除

Comment From: refeccd

既然你说不是 bug,那么抛开其他逻辑来看,只关注where条件是NotEquals的情况。 如果在启用了这个插件的情况下,代码里关于是否允许执行删除的逻辑是,只要左边不等于右边,那么就会抛出异常。

两种情况

第一种, MyBatis-Plus BlockAttackInnerInterceptor bug 左边的表达式是常量 MyBatis-Plus BlockAttackInnerInterceptor bug 右边的表达式是解析出的问号 MyBatis-Plus BlockAttackInnerInterceptor bug

第二种, MyBatis-Plus BlockAttackInnerInterceptor bug 左边的表达式是表字段 MyBatis-Plus BlockAttackInnerInterceptor bug 右边的表达式也是解析出的问号 MyBatis-Plus BlockAttackInnerInterceptor bug

上面的两种方式,都会出现我说的那种情况,因为一旦用到了ne操作,这里的 where 表达式就会是fieldName <> ?, 而插件里关于NotEquals,只要左右不等于,就会禁止操作 那么所有的不等于的删除操作都是被禁止的,所以说,难道在启用这个插件之后,我就不能进行 ne的删除吗? 那代码里关于NotEquals的判断还用写什么逻辑呢?直接返回 true,不允许ne操作不更好吗? 难道这不是个 bug 吗?

Comment From: refeccd

明显拦截器里没有考虑到,where 表达式左边是表字段的情况。 只是判断了下常量,左边是否不等于右边。 这难道不是一个明显的 bug 吗

并不觉得是bug。这正是防止全表删除的价值。如果你一定要全表删除,为什么要注入这个插件。这个插件默认是不启用的。 如果你启用了,还是有大量删除的需求,你完全可以先用ne进行查询出id,然后再用removeBatchByIds进行删除

关于后半段描述,我觉得你说的没错,有大量删除的需求,可以先 ne 查出来,再 removeBatchByIds 删除,只是我希望哪天你的 team leader 不要因为这个事把你骂了。因为数据量小无所谓,可是如果成千,上万,或者更夸张的上亿呢?你还会选择先查询出来再删这个方案吗?

Comment From: timnick-snow

直接返回 true,不允许ne操作不更好吗?

在update和delete语句中直接禁止ne也未尝不可,因为这个操作符大部分情况下都是“全表更新”或”全表删除“这样的危险行为。不过有一种例外就是,两表都是常量且相等,这样将永远返回flase,意味着不会有任何数据更新或删除。这样就没必要阻止这个sql执行了。你也许会说这样的语句是没有意义的,但是拦截器不应该抛出异常,因为这个语句不会对数据安全造成隐患。

因为数据量小无所谓,可是如果成千,上万,或者更夸张的上亿呢?你还会选择先查询出来再删这个方案吗?

数据量巨大的表执行大规模删除的行为本身就非常罕见,而驱动这种删除行为的还是事先定义好的程序,这很可能不是一个最佳的选择。如果真有数据量巨大的表需要执行类似的删除行为,可以采用分页查询再删除。或者你干脆放弃这个拦截器吧~

直接在你需要忽略这个插件校验的地方加上注解就行了

/**
 * 内置插件的一些过滤规则
 * 支持:
 * true 和 false , 1 和 0 , on 和 off
 * <p>
 * 各属性返回 true 表示不走插件(在配置了插件的情况下,不填则默认表示 false)
 *
 * @author miemie
 * @since 2020-07-31
 */
public @interface InterceptorIgnore {
    /**
     * 攻击 SQL 阻断解析器,防止全表更新与删除 {@link com.baomidou.mybatisplus.extension.plugins.inner.BlockAttackInnerInterceptor}
     */
    String blockAttack() default "";
}

Comment From: refeccd

为什么这个issue被关闭了?这不是很正常的讨论吗? 什么理由都不给,直接关了?真是厉害👍🏻

Comment From: huayanYu

上面已经告诉你解决办法了, 你觉得是BUG你就自己改下本地代码. 别智慧嘲讽JJWW