当前使用版本(必填,否则不予处理)
3.5.2
该问题是如何引起的?(确定最新版也有问题再提!!!)
通过Mapper XML自定义SQL语句,其中通过 com.baomidou.mybatisplus.extension.plugins.pagination.Page 传入分页参数,分页参数中包括 com.baomidou.mybatisplus.core.metadata.OrderItem。
代码运行时,如果自定义 SQL 语句中有自己的 orderby 字句,那么:
在 3.4.2 版本中,通过分页参数传入的 OrderItem 在所有 orderby 子句的最后面;
但是在 3.5.2 版本中,通过分页参数传入的 OrderItem 在所有 orderby 子句的最前面。
重现步骤(如果有就写完整)
例如
自定义SQL语句:select * from tableA order by field_a desc;
通过 Page 分页参数传入 page.addOrder(OrderItem.asc("field_b"));
3.4.2 版本中在运行时生成的SQL语句为:select * from tableA order by field_a desc, field_b acs;
3.5.2 版本中在运行时生成的SQL语句为:select * from tableA order by field_b acs, field_a desc;
出现了版本不兼容的问题。
报错信息
🈚️
Comment From: CodePlayer
不只是顺序有问题,我们使用如下自定义排序
queryWrapper.orderByDesc("country = 'CN' DESC");
被 MyBatis 3.5.2 处理后的 SQL 变成了 ORDER BY countryCNDESC。
导致 MySQL 报错: Cause: java.sql.SQLSyntaxErrorException: Unknown column 'countryCNDESC' in 'order clause' 。
之前 MyBatis 3.5.1 就没有这个问题。
就是因为在 @DongBingTe 在提交中 https://github.com/baomidou/mybatis-plus/commit/5ca9ccc30061314e4bbc175bb987d0be83fd6b21 调整了SQL注入的过滤规则导致的。 我不建议直接在 ORM 底层对整个SQL进行全面暴力过滤,这样很多数据库支持的增强语法都无法使用。
Comment From: DongBingTe
不只是顺序有问题,我们使用如下自定义排序
java queryWrapper.orderByDesc("country = 'CN' DESC");被 MyBatis 3.5.2 处理后的 SQL 变成了
ORDER BY countryCNDESC。 导致 MySQL 报错:Cause: java.sql.SQLSyntaxErrorException: Unknown column 'countryCNDESC' in 'order clause'。 之前 MyBatis 3.5.1 就没有这个问题。就是因为在 @DongBingTe 在提交中 5ca9ccc 调整了SQL注入的过滤规则导致的。 我不建议直接在 ORM 底层对整个SQL进行全面暴力过滤,这样很多数据库支持的增强语法都无法使用。
抱歉,我提交的pr对你的业务造成了影响,不过不得不使用暴力过滤的方式,因为在很多开源的项目中,很多会将orderBy的输入参数交给前端来传入,我想后续提交一个pr,重载orderBy的方法,使得不进行过滤。
Comment From: CodePlayer
@DongBingTe
当外部参数要参与SQL拼接的时候,我觉得这其实不应该是框架要强制暴力做的事情:
1. 全局暴力过滤,必然会带来更多的性能开销,但大多数情况下,我们并不需要从外部传入 orderBy;
2. 暴力过滤导致的后果就是,有些本来可以实现的功能,就完全没法实现了;比如我用 LIKE 模糊查询,我就是想搜索带有 % 的文本,不过这些特殊符号一旦被过滤掉,那这个功能就完全没法实现了。就像 有些网站通过过滤代码关键字 script 等来预防 XSS 注入,但是像 CSDN 这种网站,它就是需要展示用户提交的代码片段。
3. 当外部参数参与SQL拼接时,这其实也需要技术人员同步保持更高的安全意识,否则注入的SQL即使不带特殊符号,但它只需要变更传入的字段(比如预期只能传入A、B、C,但是用户传入了D)或传入一些不带特殊符号的合法的WHERE条件或函数,也能够让程序的执行结果违背预期。安全的功课光靠全局暴力过滤是不能够一劳永逸的。
4. 一个通用的 ORM 框架,更应该只做增强,不做变更。你们可以提供额外的工具方法、重载方法 或者 全局设置的开关(默认关闭,真有需要就打开),但是不应该全局暴力强制过滤,且不留下任何退路。
Comment From: DongBingTe
@DongBingTe
当外部参数要参与SQL拼接的时候,我觉得这其实不应该是框架要强制暴力做的事情:
- 全局暴力过滤,必然会带来更多的性能开销,但大多数情况下,我们并不需要从外部传入 orderBy;
- 暴力过滤导致的后果就是,有些本来可以实现的功能,就完全没法实现了;比如我用 LIKE 模糊查询,我就是想搜索带有
%的文本,不过这些特殊符号一旦被过滤掉,那这个功能就完全没法实现了。就像 有些网站通过过滤代码关键字script等来预防 XSS 注入,但是像 CSDN 这种网站,它就是需要展示用户提交的代码片段。- 当外部参数参与SQL拼接时,这其实也需要技术人员同步保持更高的安全意识,否则注入的SQL即使不带特殊符号,但它只需要变更传入的字段(比如预期只能传入A、B、C,但是用户传入了D)或传入一些不带特殊符号的合法的WHERE条件或函数,也能够让程序的执行结果违背预期。安全的功课光靠全局暴力过滤是不能够一劳永逸的。
- 一个通用的 ORM 框架,更应该只做增强,不做变更。你们可以提供额外的工具方法、重载方法 或者 全局设置的开关(默认关闭,真有需要就打开),但是不应该全局暴力强制过滤,且不留下任何退路。
我在gitee上提交了修改后的pr https://gitee.com/baomidou/mybatis-plus/pulls/270
Comment From: VampireAchao
@DongBingTe
当外部参数要参与SQL拼接的时候,我觉得这其实不应该是框架要强制暴力做的事情:
- 全局暴力过滤,必然会带来更多的性能开销,但大多数情况下,我们并不需要从外部传入 orderBy;
- 暴力过滤导致的后果就是,有些本来可以实现的功能,就完全没法实现了;比如我用 LIKE 模糊查询,我就是想搜索带有
%的文本,不过这些特殊符号一旦被过滤掉,那这个功能就完全没法实现了。就像 有些网站通过过滤代码关键字script等来预防 XSS 注入,但是像 CSDN 这种网站,它就是需要展示用户提交的代码片段。- 当外部参数参与SQL拼接时,这其实也需要技术人员同步保持更高的安全意识,否则注入的SQL即使不带特殊符号,但它只需要变更传入的字段(比如预期只能传入A、B、C,但是用户传入了D)或传入一些不带特殊符号的合法的WHERE条件或函数,也能够让程序的执行结果违背预期。安全的功课光靠全局暴力过滤是不能够一劳永逸的。
- 一个通用的 ORM 框架,更应该只做增强,不做变更。你们可以提供额外的工具方法、重载方法 或者 全局设置的开关(默认关闭,真有需要就打开),但是不应该全局暴力强制过滤,且不留下任何退路。
我非常赞同
Comment From: bbllmaster
感谢这个问题,找到临时解决办法,3.5.3.1 版本,queryWrapper.orderByDesc做了暴力过滤 page.addOrder 没做暴力过滤
Comment From: qmdx
@bbllmaster @DongBingTe 这个问题在新版本上调整为选择性过滤非默认必须,另外过滤的条件相对更加合理