Compare commits

...

57 Commits

Author SHA1 Message Date
5fa6a5e686 积木报表新版发布1.6.4 2023-10-16 12:07:41 +08:00
6d34164a16 Merge pull request #5277 from Chenzhexian/master
网关路由配置Bug问题!!!
2023-10-16 12:04:45 +08:00
e15335ddab 更新公司名称 2023-10-11 10:58:51 +08:00
b373a80498 升级driud依赖到1.2.19版本号 2023-10-11 10:58:38 +08:00
f0fb3ed5ff 升级积木报表到1.6.3版本 2023-10-11 10:57:00 +08:00
411deee8af 敲敲云零代码体验地址 2023-10-09 11:43:02 +08:00
b2942e0323 公司信息更新 2023-10-09 10:43:08 +08:00
ffeb607ad3 jeecgboot 3.5.5版本发布(数据库更新) 2023-09-21 13:59:21 +08:00
7dd68068a1 jeecgboot 3.5.5版本发布(数据库更新) 2023-09-21 13:54:22 +08:00
51d7f3b06b 解决仪表盘设计中,数据集中获取分组报错 #5416 2023-09-21 09:51:59 +08:00
a060db5530 jeecgboot 3.5.5版本发布(数据库更新) 2023-09-20 21:54:41 +08:00
30caf045ed 解决jeecg-cloud-nacos 打包镜像运行问题 #5379 2023-09-20 19:39:36 +08:00
6264b2ec70 jeecgboot 3.5.5版本发布(数据库更新) 2023-09-20 15:27:00 +08:00
9d1f73b3f7 jeecgboot 3.5.5版本发布(跳过3.5.4) 2023-09-20 14:33:20 +08:00
d557aa4cc0 jeecgboot 3.5.5版本发布(跳过3.5.4) 2023-09-20 11:58:10 +08:00
81351aeb7a dynamic-datasource-spring-boot-starter改为3.5.2稳定版本 2023-09-20 11:53:25 +08:00
ee1a568bed 升级mybatis-plus、dynamic-datasource-spring-boot-starter、commons-fileupload依赖版本号 2023-09-20 10:37:19 +08:00
e721668eb0 修改一个bug 2023-09-20 10:31:06 +08:00
5edb30c51f 只是改注释 2023-09-20 10:29:16 +08:00
9c5bd7193f 提示语修改 2023-09-20 10:28:33 +08:00
3e9b7ccfc1 vue3 online专属接口兼容 2023-09-20 10:26:05 +08:00
f1717c7000 升级mybatis-plus、driud依赖;修改配置写法 #4558 2023-09-16 22:30:55 +08:00
946d535f68 jeecg-cloud-xxljob模块中logback.xml中生成日志路径问题 #5344 2023-09-16 21:40:52 +08:00
1a326cb70f 空值问题处理 2023-09-16 21:29:01 +08:00
5a9344b190 【issues/5368】缺少租户选择套餐权限升级sql 2023-09-16 21:15:46 +08:00
4eaebd658b 空值问题处理 2023-09-16 21:15:05 +08:00
581047c569 升级积木报表1.6.2-GA5,解决仪表盘兼容问题 2023-09-12 17:26:23 +08:00
87677df925 升级积木报表1.6.2-GA3,解决严重SQL漏洞 2023-09-12 16:50:33 +08:00
56e81fbf7b 升级积木报表1.6.2-GA,解决严重SQL漏洞 2023-09-11 22:45:22 +08:00
473875a9d2 --重构表字典逻辑,深度解决SQL注入漏洞问题(修复导致的bug修复)-- 2023-09-05 22:59:08 +08:00
44952c79c2 ---重构表字典逻辑,深度解决SQL注入漏洞问题,新旧版本都可以参考此修改合并---
(重点针对表名和字段进行单独check处理,更严格的格式要求,可能会导致一些特殊字典用法出问题,请根据自己业务做灵活调整)
org\jeecg\common\exception\JeecgSqlInjectionException.java(+)
org\jeecg\common\exception\JeecgBootExceptionHandler.java

org\jeecg\common\util\security\AbstractQueryBlackListHandler.java
org\jeecg\common\util\SqlInjectionUtil.java
org\jeecg\modules\system\controller\DuplicateCheckController.java
org\jeecg\modules\system\mapper\xml\SysDictMapper.xml
org\jeecg\modules\system\mapper\SysDictMapper.java
org\jeecg\modules\system\service\impl\SysDictServiceImpl.java
org\jeecg\modules\system\service\ISysDictService.java
2023-09-03 20:07:58 +08:00
58aebdbba4 调整版本号准备发版 2023-08-31 09:48:20 +08:00
2411d85af4 Merge branch 'master' of https://github.com/zhangdaiscott/jeecg-boot 2023-08-30 19:02:34 +08:00
572ea6dd69 Mono示例 2023-08-30 19:02:00 +08:00
6e417a22ba Merge pull request #5328 from EightMonth/master
issue#5295 issue#5296 issue#5255
2023-08-30 18:50:35 +08:00
3478e8f7bc issue#5295 issue#5296 issue#5255 2023-08-30 11:38:47 +08:00
f9982a9132 【误删接口恢复】用户配置多租户后,登录后点击切换部门按钮,报错 #5298 2023-08-28 17:37:28 +08:00
d3238205e1 jeecg存在权限提升漏洞,可直接获得管理员权限 #5270 2023-08-20 18:51:43 +08:00
ff083361d4 放开系统权限控制,@RequiresPermissions,解决不安全的问题
jeecg存在权限提升漏洞,可直接获得管理员权限 #5270
2023-08-20 18:01:25 +08:00
9c038a979d 时间盲注SQL注入绕过 #5269 2023-08-20 11:32:17 +08:00
5974a2e8a4 Update DynamicRouteLoader.java 2023-08-18 09:54:20 +08:00
30151a2324 Update DynamicRouteLoader.java 2023-08-17 16:06:16 +08:00
28293aba7d Create PredicatesVo.java 2023-08-17 16:01:51 +08:00
d36caf8c69 SQL注入 #5173 2023-08-16 09:40:40 +08:00
e6bd2d5009 升级druid 2023-08-15 18:38:53 +08:00
baf4b96b3f 【漏洞处理】freemarker模板注入漏洞——升级仪表盘 2023-08-15 18:38:41 +08:00
acb48179ab 【漏洞处理】freemarker模板注入问题 禁止解析ObjectConstructor,Execute
(提示:部分依赖尚未上传maven官仓,依赖下载失败请配置jeecg私服)
2023-08-15 17:45:07 +08:00
20889e8724 【issues/4393】解决使用参数tableName=sys_user t&复测,漏洞仍然存在 2023-08-14 15:54:03 +08:00
751b81c7bf 【issues/4393】解决使用参数tableName=sys_user t&复测,漏洞仍然存在 2023-08-14 12:51:31 +08:00
0bc7e0967d 【issues/4393】解决使用参数tableName=sys_user t&复测,漏洞仍然存在 2023-08-14 10:01:49 +08:00
05181754bb 签名失败 2023-08-09 20:45:49 +08:00
5ab62d5d3b 解决Apache Shiro高危漏洞编号:CVE-2023-34478 2023-07-25 11:31:54 +08:00
83d96bf89e JeecgBoot 低代码平台 3.5.3 版本发布,Online 功能专题升级 2023-07-24 11:51:45 +08:00
0b2c966a72 README 更新 2023-07-24 11:11:49 +08:00
ffda530daa README 更新 2023-07-24 11:06:18 +08:00
4c0641f374 README 更新 2023-07-24 10:20:12 +08:00
54c7c034a4 JeecgBoot 低代码平台 3.5.3 版本发布,Online 功能专题升级 2023-07-24 10:11:12 +08:00
90 changed files with 5685 additions and 4679 deletions

View File

@ -203,7 +203,7 @@
In any case, you must not make any such use of this software as to develop software which may be considered competitive with this software.
开源协议补充
JeecgBoot 是由 北京敲敲云科技有限公司 发行的软件。 总部位于北京地址中国·北京·朝阳区科荟前街1号院奥林佳泰大厦。邮箱jeecgos@163.com
JeecgBoot 是由 北京国炬信息技术有限公司 发行的软件。 总部位于北京地址中国·北京·朝阳区科荟前街1号院奥林佳泰大厦。邮箱jeecgos@163.com
本软件受适用的国家软件著作权法(包括国际条约)和双重保护许可。
1.允许基于本平台软件开展业务系统开发。

View File

@ -7,13 +7,13 @@
JEECG BOOT Low Code Development Platform
===============
The Latest Version 3.5.3Release date2023-07-24
The Latest Version 3.5.5Release date2023-09-22
[![AUR](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE)
[![](https://img.shields.io/badge/Author-qiaoqiaoyun-orange.svg)](http://www.jeecg.com)
[![](https://img.shields.io/badge/Author-guojusoft-orange.svg)](http://www.jeecg.com)
[![](https://img.shields.io/badge/Blog-blog-blue.svg)](https://jeecg.blog.csdn.net)
[![](https://img.shields.io/badge/version-3.5.3-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot)
[![](https://img.shields.io/badge/version-3.5.5-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot)
[![GitHub stars](https://img.shields.io/github/stars/zhangdaiscott/jeecg-boot.svg?style=social&label=Stars)](https://github.com/zhangdaiscott/jeecg-boot)
[![GitHub forks](https://img.shields.io/github/forks/zhangdaiscott/jeecg-boot.svg?style=social&label=Fork)](https://github.com/zhangdaiscott/jeecg-boot)
@ -44,10 +44,12 @@ Official Support: http://jeecg.com/doc/help
Download the source code
-----------------------------------
- The background source https://github.com/jeecgboot/jeecg-boot
- Front-end source (Vue3 version)https://github.com/jeecgboot/jeecgboot-vue3
- Front-end source (Vue2 version)https://github.com/jeecgboot/ant-design-vue-jeecg
- APP Supporting frameworkhttps://github.com/jeecgboot/jeecg-uniapp
项目源码
-----------------------------------
| Source |Front-end source (Vue3 version) | Front-end source (Vue2 version) | The background source |
|-|-|-|-|
| Github | [jeecgboot-vue3](https://github.com/jeecgboot/jeecgboot-vue3) | [ant-design-vue-jeecg](https://github.com/jeecgboot/ant-design-vue-jeecg) | [jeecg-boot](https://github.com/jeecgboot/jeecg-boot) |
| Gitee | [jeecgboot-vue3](https://gitee.com/jeecg/jeecgboot-vue3) | [ant-design-vue-jeecg](https://gitee.com/jeecg/ant-design-vue-jeecg) | [jeecg-boot](https://gitee.com/jeecg/jeecg-boot) |
##### Project description
@ -56,9 +58,9 @@ Download the source code
| `jeecg-boot` | SpringBoot background source code (support microservices) |
| `jeecgboot-vue3` | Vue3+TS new front-end source code|
| `ant-design-vue-jeecg` |Vue2 version front-end source code |
| `jeecg-uniapp` | APP development framework, a code multi terminal adaptation, and support APP, small program, H5 |
| `jeecg-uniapp` | [APP development framework, a code multi terminal adaptation, and support APP, small program, H5](https://github.com/jeecgboot/jeecg-uniapp) |
| `jeecg-boot-starter` | [Stater relies on the project to be maintained separately. Click Download](https://gitee.com/jeecg/jeecg-boot-starter) |
| `More` | [Download more source code](https://github.com/jeecgboot) |
| `More` | [Download more source code](http://jeecg.com/download) |
@ -84,16 +86,12 @@ Technical documentation
-----------------------------------
- Website [http://www.jeecg.com](http://www.jeecg.com)
- Demo [Vue3](http://boot3.jeecg.com) | [Vue2](http://boot.jeecg.com)
- Doc [http://help.jeecg.com](http://help.jeecg.com)
- Newbie guide [Quick start](http://www.jeecg.com/doc/quickstart) | [video](https://space.bilibili.com/454617261/channel/series) | [Q&A ](http://www.jeecg.com/doc/qa) | [help](http://jeecg.com/doc/help) | [1 minute experience](https://my.oschina.net/jeecg/blog/3083313)
- Microservice Development [Monomer upgrade to microservice](https://help.jeecg.com/java/springcloud/switchcloud/monomer.html)
- QQ group ⑦791696430、⑥730954414、683903138、⑤860162132(full)、④774126647(full)、③816531124(full)、②769925425(full)、①284271917(full)
- Demo [Vue3](http://boot3.jeecg.com) | [Vue2](http://boot.jeecg.com) | [APP](http://jeecg.com/appIndex)
> [please click obtain account password to obtain](http://jeecg.com/doc/demo)

View File

@ -7,13 +7,13 @@
JEECG BOOT 低代码开发平台
===============
当前最新版本: 3.5.3发布日期2023-07-24
当前最新版本: 3.5.5发布日期2023-09-22
[![AUR](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg)](https://github.com/zhangdaiscott/jeecg-boot/blob/master/LICENSE)
[![](https://img.shields.io/badge/Author-北京敲敲云科技-orange.svg)](http://www.jeecg.com)
[![](https://img.shields.io/badge/Author-北京国炬软件-orange.svg)](http://jeecg.com/aboutusIndex)
[![](https://img.shields.io/badge/Blog-官方博客-blue.svg)](https://jeecg.blog.csdn.net)
[![](https://img.shields.io/badge/version-3.5.3-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot)
[![](https://img.shields.io/badge/version-3.5.5-brightgreen.svg)](https://github.com/zhangdaiscott/jeecg-boot)
[![GitHub stars](https://img.shields.io/github/stars/zhangdaiscott/jeecg-boot.svg?style=social&label=Stars)](https://github.com/zhangdaiscott/jeecg-boot)
[![GitHub forks](https://img.shields.io/github/forks/zhangdaiscott/jeecg-boot.svg?style=social&label=Fork)](https://github.com/zhangdaiscott/jeecg-boot)
@ -33,36 +33,65 @@ JeecgBoot 提供了一系列`低代码模块`,实现在线开发`真正的零
`JEECG业务流程:` 采用工作流来实现、扩展出任务接口,供开发编写业务逻辑,表单提供多种解决方案: 表单设计器、online配置表单、编码表单。同时实现了流程与表单的分离设计松耦合、并支持任务节点灵活配置既保证了公司流程的保密性又减少了开发人员的工作量。
遇到技术问题,[请在这里反馈BUG](https://github.com/jeecgboot/jeecg-boot/issues/new)
适用项目
-----------------------------------
Jeecg-Boot低代码开发平台可以应用在任何J2EE项目的开发中尤其适合SAAS项目、企业信息管理系统MIS、内部办公系统OA、企业资源计划系统ERP、客户关系管理系统CRM其半智能手工Merge的开发方式可以显著提高开发效率70%以上,极大降低开发成本。
源码下载
项目源码
-----------------------------------
| 仓库 |前端 Vue3版 | 前端 Vue2版 | 后端源码 |
|-|-|-|-|
| Github | [jeecgboot-vue3](https://github.com/jeecgboot/jeecgboot-vue3) | [ant-design-vue-jeecg](https://github.com/jeecgboot/ant-design-vue-jeecg) | [jeecg-boot](https://github.com/jeecgboot/jeecg-boot) |
| 码云 | [jeecgboot-vue3](https://gitee.com/jeecg/jeecgboot-vue3) | [ant-design-vue-jeecg](https://gitee.com/jeecg/ant-design-vue-jeecg) | [jeecg-boot](https://gitee.com/jeecg/jeecg-boot) |
| 源码 | 源码地址 |
|--------------------|------------------------|
| 后台源码 JAVA | https://github.com/jeecgboot/jeecg-boot |
| 前端源码 `Vue3版` | https://github.com/jeecgboot/jeecgboot-vue3 |
| APP配套框架 | https://github.com/jeecgboot/jeecg-uniapp |
##### 快速搭建开发环境
- [通过IDEA启动前后端项目](https://help.jeecg.com/java/setup/idea/startup.html)
- [Vue3前端项目快速启动](http://help.jeecg.com/setup/startup.html)
- [单体快速切换为微服务版](https://help.jeecg.com/java/springcloud/switchcloud/monomer.html)
##### 项目说明
#### 项目说明
| 项目名 | 说明 |
|--------------------|------------------------|
| `jeecg-boot` | SpringBoot后台源码支持微服务 |
| `jeecgboot-vue3` | Vue3+TS 新版前端源码 |
| `jeecg-uniapp` | APP开发框架一份代码多终端适配同时支持APP、小程序、H5 |
| `ant-design-vue-jeecg` |Vue2版前端源码 |
| `jeecg-uniapp` | [APP开发框架一份代码多终端适配同时支持APP、小程序、H5](https://github.com/jeecgboot/jeecg-uniapp) |
| `jeecg-boot-starter` | [Stater依赖项目单独维护点击下载](https://gitee.com/jeecg/jeecg-boot-starter) |
| `更多开源插件` | [更多源码下载](https://github.com/jeecgboot) |
| `更多开源项目` | [更多源码下载](http://jeecg.com/download) |
快速搭建开发环境
-----------------------------------
- [通过IDEA导入项目](https://help.jeecg.com/java/setup/idea.html)
- [通过IDEA启动前后端项目](https://help.jeecg.com/java/setup/idea/startup.html)
- [Vue3前端项目快速启动](http://help.jeecg.com/setup/startup.html)
- [单体快速切换为微服务版](https://help.jeecg.com/java/springcloud/switchcloud/monomer.html)
Docker快速启动项目
-----------------------------------
- [Docker启动单体后台](https://help.jeecg.com/java/setup/docker/up.html)
- [Docker启动Vue3前端](http://help.jeecg.com/publish/docker.html)
- [Docker启动微服务后台](https://help.jeecg.com/java/springcloud/docker.html)
技术文档
-----------------------------------
- 项目官网: [http://www.jeecg.com](http://www.jeecg.com)
- 开发文档: [http://help.jeecg.com](http://help.jeecg.com)
- 新手指南: [快速入门](http://www.jeecg.com/doc/quickstart) | [常见问题 ](http://www.jeecg.com/doc/qa) | [视频教程](https://space.bilibili.com/454617261/channel/series) | [1分钟低代码体验](https://my.oschina.net/jeecg/blog/3083313)
- 在线演示 [Vue3演示](http://boot3.jeecg.com) | [APP演示](http://jeecg.com/appIndex) | [敲敲云零代码](https://qiaoqiaoyun.com)
> 演示系统的登录账号密码,请点击 [获取账号密码](http://jeecg.com/doc/demo) 获取
>
- QQ交流群 ⑦791696430、⑥730954414、VUE3群683903138、⑤860162132(满)、④774126647(满)、③816531124(满)、②769925425(满)、①284271917(满)
> ` 提醒【QQ群是自助服务群建议给帮助您解决问题的同学发送指定红包表示感谢】 `
@ -74,31 +103,6 @@ Jeecg-Boot低代码开发平台可以应用在任何J2EE项目的开发中
官方支持: [http://jeecg.com/doc/help](http://jeecg.com/doc/help)
技术文档
-----------------------------------
- 项目官网: [http://www.jeecg.com](http://www.jeecg.com)
- 在线演示 [低代码演示](http://boot3.jeecg.com) | [零代码体验](http://app.qiaoqiaoyun.com)
- 开发文档: [http://help.jeecg.com](http://help.jeecg.com)
- 新手指南: [快速入门](http://www.jeecg.com/doc/quickstart) | [常见问题 ](http://www.jeecg.com/doc/qa) | [视频教程](https://space.bilibili.com/454617261/channel/series) | [1分钟低代码体验](https://my.oschina.net/jeecg/blog/3083313)
- QQ交流群 ⑦791696430、⑥730954414、VUE3群683903138、⑤860162132(满)、④774126647(满)、③816531124(满)、②769925425(满)、①284271917(满)
> ` 提醒【QQ群是自助服务群建议给帮助您解决问题的同学发送指定红包表示感谢】 `
Docker启动项目
-----------------------------------
- [Docker启动单体后台](https://help.jeecg.com/java/setup/docker/up.html)
- [Docker启动Vue3前端](http://help.jeecg.com/publish/docker.html)
- [Docker启动微服务后台](https://help.jeecg.com/java/springcloud/docker.html)
=======【VUE2版本专题介绍】============================================

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,49 @@
-- 产品包升级sql
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('1609123240547344385', '1280350452934307841', '产品包分页列表查询', NULL, NULL, 0, NULL, NULL, 2, 'system:tenant:packList', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2022-12-31 17:44:11', NULL, NULL, 0, 0, '1', 0);
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('1609123437247619074', '1280350452934307841', '创建租户产品包', NULL, NULL, 0, NULL, NULL, 2, 'system:tenant:add:pack', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2022-12-31 17:44:58', 'admin', '2022-12-31 20:27:56', 0, 0, '1', 0);
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('1609164542165012482', '1280350452934307841', '编辑租户产品包', NULL, NULL, 0, NULL, NULL, 2, 'system:tenant:edit:pack', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2022-12-31 20:28:18', NULL, NULL, 0, 0, '1', 0);
INSERT INTO sys_permission(id, parent_id, name, url, component, is_route, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_leaf, keep_alive, hidden, hide_tab, description, create_by, create_time, update_by, update_time, del_flag, rule_flag, status, internal_or_external) VALUES ('1609164635442139138', '1280350452934307841', '批量删除租户产品包', NULL, NULL, 0, NULL, NULL, 2, 'system:tenant:delete:pack', '1', NULL, 0, NULL, 1, 0, 0, 0, NULL, 'admin', '2022-12-31 20:28:41', NULL, NULL, 0, 0, '1', 0);
-- 新增部门默认是叶子节点即没有子节点
ALTER TABLE sys_depart
MODIFY COLUMN iz_leaf tinyint(1) NULL DEFAULT 1 COMMENT '是否有叶子节点: 1是0否' AFTER tenant_id;
-- 部门数据错了修复---
update sys_depart set iz_leaf = 0 where id in ( select a.parent_id from (select parent_id from sys_depart where parent_id!='' and parent_id is not null) as a);
update sys_depart set iz_leaf = 1 where id not in ( select a.parent_id from (select parent_id from sys_depart where parent_id!='' and parent_id is not null) as a);
-- 日志接口类没有加权限注解
-- vue2
UPDATE sys_permission_v2 SET is_leaf = 0 WHERE id = '58857ff846e61794c69208e9d3a85466';
INSERT INTO sys_permission_v2(id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_route, is_leaf, keep_alive, hidden, hide_tab, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external) VALUES ('1660568280725127169', '58857ff846e61794c69208e9d3a85466', '日志列表', NULL, NULL, NULL, NULL, 2, 'system:log:list', '1', NULL, 0, NULL, 1, 1, 0, 0, 0, NULL, '1', 0, 0, 'admin', '2023-05-22 16:48:25', NULL, NULL, 0);
INSERT INTO sys_permission_v2(id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_route, is_leaf, keep_alive, hidden, hide_tab, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external) VALUES ('1660568368558047234', '58857ff846e61794c69208e9d3a85466', '日志删除', NULL, NULL, NULL, NULL, 2, 'system:log:delete', '1', NULL, 0, NULL, 1, 1, 0, 0, 0, NULL, '1', 0, 0, 'admin', '2023-05-22 16:48:46', NULL, NULL, 0);
INSERT INTO sys_permission_v2(id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_route, is_leaf, keep_alive, hidden, hide_tab, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external) VALUES ('1660568426632380417', '58857ff846e61794c69208e9d3a85466', '日志批量删除', NULL, NULL, NULL, NULL, 2, 'system:log:deleteBatch', '1', NULL, 0, NULL, 1, 1, 0, 0, 0, NULL, '1', 0, 0, 'admin', '2023-05-22 16:48:59', NULL, NULL, 0);
-- vue3
UPDATE sys_permission SET is_leaf = 0 WHERE id = '1439533711676973057';
INSERT INTO sys_permission(id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_route, is_leaf, keep_alive, hidden, hide_tab, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external) VALUES ('1660568280725127169', '1439533711676973057', '日志列表', NULL, NULL, NULL, NULL, 2, 'system:log:list', '1', NULL, 0, NULL, 1, 1, 0, 0, 0, NULL, '1', 0, 0, 'admin', '2023-05-22 16:48:25', NULL, NULL, 0);
INSERT INTO sys_permission(id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_route, is_leaf, keep_alive, hidden, hide_tab, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external) VALUES ('1660568368558047234', '1439533711676973057', '日志删除', NULL, NULL, NULL, NULL, 2, 'system:log:delete', '1', NULL, 0, NULL, 1, 1, 0, 0, 0, NULL, '1', 0, 0, 'admin', '2023-05-22 16:48:46', NULL, NULL, 0);
INSERT INTO sys_permission(id, parent_id, name, url, component, component_name, redirect, menu_type, perms, perms_type, sort_no, always_show, icon, is_route, is_leaf, keep_alive, hidden, hide_tab, description, status, del_flag, rule_flag, create_by, create_time, update_by, update_time, internal_or_external) VALUES ('1660568426632380417', '1439533711676973057', '日志批量删除', NULL, NULL, NULL, NULL, 2, 'system:log:deleteBatch', '1', NULL, 0, NULL, 1, 1, 0, 0, 0, NULL, '1', 0, 0, 'admin', '2023-05-22 16:48:59', NULL, NULL, 0);
-- 字段长度不够 ---
ALTER TABLE sys_data_log
MODIFY COLUMN `data_table` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '表名' AFTER `update_time`;
-- 系统通知卡顿问题性能优化 ---
ALTER TABLE `sys_announcement_send`
ADD INDEX `idx_sacm_annt_id`(`annt_id`),
ADD INDEX `idx_sacm_user_id`(`user_id`),
ADD INDEX `idx_sacm_read_flag`(`read_flag`),
ADD INDEX `idx_sacm_star_flag`(`star_flag`);
ALTER TABLE `sys_announcement`
ADD INDEX `idx_sanno_endtime`(`end_time`),
ADD INDEX `idx_sanno_start_time`(`start_time`),
ADD INDEX `idx_sanno_msg_type`(`msg_type`),
ADD INDEX `idx_sanno_send_status`(`send_status`),
ADD INDEX `idx_sanno_del_flag`(`del_flag`),
ADD INDEX `idx_sanno_tenant_id`(`tenant_id`),
ADD INDEX `idx_sanno_sender`(`sender`),
ADD INDEX `idx_sanno_create_time`(`create_time`);

View File

@ -7,4 +7,5 @@
2.数据库升级 => 针对数据库我们每次发布会提供增量升级SQL可以通过增量SQL实现数据库的升级。
3.兼容问题 => 每次版本发布会针对不兼容地方标注说明,需要手工修改不兼容的代码。
注意: 升级sql目前只提供mysql版本执行完脚步后新菜单需要手工进行角色授权刷新首页才会出现。
注意: 升级sql目前只提供mysql版本执行完脚步后新菜单需要手工进行角色授权刷新首页才会出现。
【20230820 放开了系统管理等模块权限注解,如果没权限请通过角色授权授权对应的按钮权限】

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-parent</artifactId>
<version>3.5.3</version>
<version>3.5.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-boot-base-core</artifactId>

View File

@ -59,8 +59,7 @@ public class PermissionDataAspect {
requestPath = filterUrl(requestPath);
//update-begin-author:taoyan date:20211027 for:JTC-132【online报表权限】online报表带参数的菜单配置数据权限无效
//先判断是否online报表请求
// TODO 参数顺序调整有隐患
if(requestPath.indexOf(UrlMatchEnum.CGREPORT_DATA.getMatchUrl())>=0){
if(requestPath.indexOf(UrlMatchEnum.CGREPORT_DATA.getMatchUrl())>=0 || requestPath.indexOf(UrlMatchEnum.CGREPORT_ONLY_DATA.getMatchUrl())>=0){
// 获取地址栏参数
String urlParamString = request.getParameter(CommonConstant.ONL_REP_URL_PARAM_STR);
if(oConvertUtils.isNotEmpty(urlParamString)){
@ -68,7 +67,7 @@ public class PermissionDataAspect {
}
}
//update-end-author:taoyan date:20211027 for:JTC-132【online报表权限】online报表带参数的菜单配置数据权限无效
log.info("拦截请求 >> {} ; 请求类型 >> {} . ", requestPath, requestMethod);
log.debug("拦截请求 >> {} ; 请求类型 >> {} . ", requestPath, requestMethod);
String username = JwtUtil.getUserNameByToken(request);
//查询数据权限信息
//TODO 微服务情况下也得支持缓存机制

View File

@ -14,6 +14,8 @@ public enum UrlMatchEnum {
CGFORM_TREE_DATA("/online/cgform/api/getTreeData/", "/online/cgformList/"),
/**求URL与菜单路由URL转换规则 /online/cgreport/api/getColumnsAndData/ */
CGREPORT_DATA("/online/cgreport/api/getColumnsAndData/", "/online/cgreport/"),
/** 求URL与菜单路由URL转换规则/online/cgreport/api/getData/ 【vue3报表数据请求地址】 */
CGREPORT_ONLY_DATA("/online/cgreport/api/getData/", "/online/cgreport/"),
/**求URL与菜单路由URL转换规则 /online/cgreport/api/exportXls/ */
CGREPORT_EXCEL_DATA("/online/cgreport/api/exportXls/", "/online/cgreport/"),
/**求URL与菜单路由URL转换规则 /online/cgreport/api/exportManySheetXls/ */

View File

@ -1,6 +1,7 @@
package org.jeecg.common.exception;
import cn.hutool.core.util.ObjectUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.UnauthorizedException;
import org.jeecg.common.api.vo.Result;
@ -16,8 +17,6 @@ import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.NoHandlerFoundException;
import lombok.extern.slf4j.Slf4j;
/**
* 异常处理器
*
@ -133,4 +132,24 @@ public class JeecgBootExceptionHandler {
return Result.error("Redis 连接异常!");
}
/**
* SQL注入风险全局异常处理
*
* @param exception
* @return
*/
@ExceptionHandler(JeecgSqlInjectionException.class)
public Result<?> handleSQLException(Exception exception) {
String msg = exception.getMessage().toLowerCase();
final String extractvalue = "extractvalue";
final String updatexml = "updatexml";
boolean hasSensitiveInformation = msg.indexOf(extractvalue) >= 0 || msg.indexOf(updatexml) >= 0;
if (msg != null && hasSensitiveInformation) {
log.error("校验失败存在SQL注入风险{}", msg);
return Result.error("校验失败存在SQL注入风险");
}
return Result.error("校验失败存在SQL注入风险" + msg);
}
}

View File

@ -0,0 +1,23 @@
package org.jeecg.common.exception;
/**
* @Description: jeecg-boot自定义SQL注入异常
* @author: jeecg-boot
*/
public class JeecgSqlInjectionException extends RuntimeException {
private static final long serialVersionUID = 1L;
public JeecgSqlInjectionException(String message){
super(message);
}
public JeecgSqlInjectionException(Throwable cause)
{
super(cause);
}
public JeecgSqlInjectionException(String message, Throwable cause)
{
super(message,cause);
}
}

View File

@ -1,11 +1,12 @@
package org.jeecg.common.util;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.creator.DataSourceProperty;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.DataBaseConstant;
import org.jeecg.common.constant.ServiceNameConstants;
@ -26,6 +27,7 @@ import java.io.InputStream;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -145,7 +147,7 @@ public class CommonUtils {
* @param bizPath 自定义路径
* @return
*/
public static String uploadLocal(MultipartFile mf,String bizPath,String uploadpath){
public static String uploadLocal(MultipartFile mf, String bizPath, String uploadpath){
try {
//update-begin-author:liusq date:20210809 for: 过滤上传文件类型
FileTypeFilter.fileTypeFilter(mf);
@ -272,7 +274,7 @@ public class CommonUtils {
if(db==null){
return null;
}
DriverManagerDataSource ds = new DriverManagerDataSource ();
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName(db.getDriverClassName());
ds.setUrl(db.getUrl());
ds.setUsername(db.getUsername());
@ -392,4 +394,47 @@ public class CommonUtils {
return target;
}
/**
* 将list集合以分割符的方式进行分割
* @param list String类型的集合文本
* @param separator 分隔符
* @return
*/
public static String getSplitText(List<String> list, String separator) {
if (null != list && list.size() > 0) {
return StringUtils.join(list, separator);
}
return "";
}
/**
* 通过table的条件SQL
*
* @param tableSql sys_user where name = '1212'
* @return name = '1212'
*/
public static String getFilterSqlByTableSql(String tableSql) {
if (tableSql.toLowerCase().indexOf(DataBaseConstant.SQL_WHERE) > 0) {
String[] arr = tableSql.split(" (?i)where ");
if (arr != null && oConvertUtils.isNotEmpty(arr[1])) {
return arr[1];
}
}
return "";
}
/**
* 通过table获取表名
*
* @param tableSql sys_user where name = '1212'
* @return sys_user
*/
public static String getTableNameByTableSql(String tableSql) {
if (tableSql.toLowerCase().indexOf(DataBaseConstant.SQL_WHERE) > 0) {
String[] arr = tableSql.split(" (?i)where ");
return arr[0].trim();
} else {
return tableSql;
}
}
}

View File

@ -2,7 +2,10 @@ package org.jeecg.common.util;
import cn.hutool.crypto.SecureUtil;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.exception.JeecgSqlInjectionException;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.util.Set;
@ -33,7 +36,7 @@ public class SqlInjectionUtil {
/**
* sleep函数
*/
private final static Pattern FUN_SLEEP = Pattern.compile("sleep\\([\\d\\.]*\\)");
private final static Pattern FUN_SLEEP = Pattern.compile("sleep\\(.*\\)", Pattern.CASE_INSENSITIVE);
/**
* sql注释的正则
@ -47,7 +50,7 @@ public class SqlInjectionUtil {
* @param request:
* @Return: void
*/
public static void checkDictTableSign(String dictCode, String sign, HttpServletRequest request) {
private static void checkDictTableSign(String dictCode, String sign, HttpServletRequest request) {
//表字典SQL注入漏洞,签名校验
String accessToken = request.getHeader("X-Access-Token");
String signStr = dictCode + SqlInjectionUtil.TABLE_DICT_SIGN_SALT + accessToken;
@ -60,11 +63,76 @@ public class SqlInjectionUtil {
}
/**
* 返回查询表名
* <p>
* sql注入过滤处理遇到注入关键字抛异常
* @param value
*
* @param table
*/
public static void filterContent(String value) {
filterContent(value, null);
private static Pattern tableNamePattern = Pattern.compile("^[a-zA-Z][a-zA-Z0-9_]{0,63}$");
public static String getSqlInjectTableName(String table) {
table = table.trim();
/**
* 检验表名是否合法
*
* 表名只能由字母、数字和下划线组成。
* 表名必须以字母开头。
* 表名长度通常有限制,例如最多为 64 个字符。
*/
boolean isValidTableName = tableNamePattern.matcher(table).matches();
if (!isValidTableName) {
String errorMsg = "表名不合法存在SQL注入风险!--->" + table;
log.error(errorMsg);
throw new JeecgSqlInjectionException(errorMsg);
}
//进一步验证是否存在SQL注入风险
filterContent(table);
return table;
}
/**
* 返回查询字段
* <p>
* sql注入过滤处理遇到注入关键字抛异常
*
* @param field
*/
static final Pattern fieldPattern = Pattern.compile("^[a-zA-Z0-9_]+$");
public static String getSqlInjectField(String field) {
if(oConvertUtils.isEmpty(field)){
return null;
}
field = field.trim();
if (field.contains(SymbolConstant.COMMA)) {
return getSqlInjectField(field.split(SymbolConstant.COMMA));
}
/**
* 校验表字段是否有效
*
* 字段定义只能是是字母 数字 下划线的组合(不允许有空格、转义字符串等)
*/
boolean isValidField = fieldPattern.matcher(field).matches();
if (!isValidField) {
String errorMsg = "字段不合法存在SQL注入风险!--->" + field;
log.error(errorMsg);
throw new JeecgSqlInjectionException(errorMsg);
}
//进一步验证是否存在SQL注入风险
filterContent(field);
return field;
}
public static String getSqlInjectField(String... fields) {
for (String s : fields) {
getSqlInjectField(s);
}
return String.join(SymbolConstant.COMMA, fields);
}
/**
@ -89,7 +157,7 @@ public class SqlInjectionUtil {
if (value.indexOf(xssArr[i]) > -1) {
log.error("请注意存在SQL注入关键词---> {}", xssArr[i]);
log.error("请注意值可能存在SQL注入风险!---> {}", value);
throw new RuntimeException("请注意值可能存在SQL注入风险!--->" + value);
throw new JeecgSqlInjectionException("请注意值可能存在SQL注入风险!--->" + value);
}
}
//update-begin-author:taoyan date:2022-7-13 for: 除了XSS_STR这些提前设置好的还需要额外的校验比如 单引号
@ -99,13 +167,13 @@ public class SqlInjectionUtil {
if (value.indexOf(xssArr2[i]) > -1) {
log.error("请注意存在SQL注入关键词---> {}", xssArr2[i]);
log.error("请注意值可能存在SQL注入风险!---> {}", value);
throw new RuntimeException("请注意值可能存在SQL注入风险!--->" + value);
throw new JeecgSqlInjectionException("请注意值可能存在SQL注入风险!--->" + value);
}
}
}
//update-end-author:taoyan date:2022-7-13 for: 除了XSS_STR这些提前设置好的还需要额外的校验比如 单引号
if(Pattern.matches(SHOW_TABLES, value) || Pattern.matches(REGULAR_EXPRE_USER, value)){
throw new RuntimeException("请注意值可能存在SQL注入风险!--->" + value);
throw new JeecgSqlInjectionException("请注意值可能存在SQL注入风险!--->" + value);
}
return;
}
@ -114,7 +182,7 @@ public class SqlInjectionUtil {
* sql注入过滤处理遇到注入关键字抛异常
* @param values
*/
public static void filterContent(String[] values) {
public static void filterContent(String... values) {
filterContent(values, null);
}
@ -141,7 +209,7 @@ public class SqlInjectionUtil {
if (value.indexOf(xssArr[i]) > -1) {
log.error("请注意存在SQL注入关键词---> {}", xssArr[i]);
log.error("请注意值可能存在SQL注入风险!---> {}", value);
throw new RuntimeException("请注意值可能存在SQL注入风险!--->" + value);
throw new JeecgSqlInjectionException("请注意值可能存在SQL注入风险!--->" + value);
}
}
//update-begin-author:taoyan date:2022-7-13 for: 除了XSS_STR这些提前设置好的还需要额外的校验比如 单引号
@ -151,13 +219,13 @@ public class SqlInjectionUtil {
if (value.indexOf(xssArr2[i]) > -1) {
log.error("请注意存在SQL注入关键词---> {}", xssArr2[i]);
log.error("请注意值可能存在SQL注入风险!---> {}", value);
throw new RuntimeException("请注意值可能存在SQL注入风险!--->" + value);
throw new JeecgSqlInjectionException("请注意值可能存在SQL注入风险!--->" + value);
}
}
}
//update-end-author:taoyan date:2022-7-13 for: 除了XSS_STR这些提前设置好的还需要额外的校验比如 单引号
if(Pattern.matches(SHOW_TABLES, value) || Pattern.matches(REGULAR_EXPRE_USER, value)){
throw new RuntimeException("请注意值可能存在SQL注入风险!--->" + value);
throw new JeecgSqlInjectionException("请注意值可能存在SQL注入风险!--->" + value);
}
}
return;
@ -188,11 +256,11 @@ public class SqlInjectionUtil {
if (value.indexOf(xssArr[i]) > -1 || value.startsWith(xssArr[i].trim())) {
log.error("请注意存在SQL注入关键词---> {}", xssArr[i]);
log.error("请注意值可能存在SQL注入风险!---> {}", value);
throw new RuntimeException("请注意值可能存在SQL注入风险!--->" + value);
throw new JeecgSqlInjectionException("请注意值可能存在SQL注入风险!--->" + value);
}
}
if(Pattern.matches(SHOW_TABLES, value) || Pattern.matches(REGULAR_EXPRE_USER, value)){
throw new RuntimeException("请注意值可能存在SQL注入风险!--->" + value);
throw new JeecgSqlInjectionException("请注意值可能存在SQL注入风险!--->" + value);
}
return;
}
@ -222,12 +290,12 @@ public class SqlInjectionUtil {
if (value.indexOf(xssArr[i]) > -1 || value.startsWith(xssArr[i].trim())) {
log.error("请注意存在SQL注入关键词---> {}", xssArr[i]);
log.error("请注意值可能存在SQL注入风险!---> {}", value);
throw new RuntimeException("请注意值可能存在SQL注入风险!--->" + value);
throw new JeecgSqlInjectionException("请注意值可能存在SQL注入风险!--->" + value);
}
}
if(Pattern.matches(SHOW_TABLES, value) || Pattern.matches(REGULAR_EXPRE_USER, value)){
throw new RuntimeException("请注意值可能存在SQL注入风险!--->" + value);
throw new JeecgSqlInjectionException("请注意值可能存在SQL注入风险!--->" + value);
}
return;
}
@ -285,7 +353,7 @@ public class SqlInjectionUtil {
if(matcher.find()){
String error = "请注意值可能存在SQL注入风险---> \\*.*\\";
log.error(error);
throw new RuntimeException(error);
throw new JeecgSqlInjectionException(error);
}
// issues/4737 sys/duplicate/check SQL注入 #4737
@ -293,7 +361,7 @@ public class SqlInjectionUtil {
if(sleepMatcher.find()){
String error = "请注意值可能存在SQL注入风险---> sleep";
log.error(error);
throw new RuntimeException(error);
throw new JeecgSqlInjectionException(error);
}
}
}

View File

@ -34,11 +34,11 @@ public class FreemarkerParseFactory {
/**
* 文件缓存
*/
private static final Configuration TPL_CONFIG = new Configuration();
private static final Configuration TPL_CONFIG = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
/**
* SQL 缓存
*/
private static final Configuration SQL_CONFIG = new Configuration();
private static final Configuration SQL_CONFIG = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
private static StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
@ -47,8 +47,7 @@ public class FreemarkerParseFactory {
.compile("(?ms)/\\*.*?\\*/|^\\s*//.*?$");
static {
TPL_CONFIG.setClassForTemplateLoading(
new FreemarkerParseFactory().getClass(), "/");
TPL_CONFIG.setClassForTemplateLoading(new FreemarkerParseFactory().getClass(), "/");
TPL_CONFIG.setNumberFormat("0.#####################");
SQL_CONFIG.setTemplateLoader(stringTemplateLoader);
SQL_CONFIG.setNumberFormat("0.#####################");
@ -57,6 +56,7 @@ public class FreemarkerParseFactory {
//update-begin-author:taoyan date:2022-8-10 for: freemarker模板注入问题 禁止解析ObjectConstructorExecute和freemarker.template.utility.JythonRuntime。
//https://ackcent.com/in-depth-freemarker-template-injection/
TPL_CONFIG.setNewBuiltinClassResolver(TemplateClassResolver.SAFER_RESOLVER);
SQL_CONFIG.setNewBuiltinClassResolver(TemplateClassResolver.SAFER_RESOLVER);
//update-end-author:taoyan date:2022-8-10 for: freemarker模板注入问题 禁止解析ObjectConstructorExecute和freemarker.template.utility.JythonRuntime。
}
@ -169,7 +169,7 @@ public class FreemarkerParseFactory {
//"where and"
String whereAnd = DataBaseConstant.SQL_WHERE+" and";
//", where"
String commaWhere = SymbolConstant.COMMA+" "+DataBaseConstant.SQL_WHERE;
String commaWhere = SymbolConstant.COMMA+" "+ DataBaseConstant.SQL_WHERE;
//", "
String commaSpace = SymbolConstant.COMMA + " ";
if (sql.endsWith(DataBaseConstant.SQL_WHERE) || sql.endsWith(whereSpace)) {

View File

@ -1,6 +1,8 @@
package org.jeecg.common.util.security;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.exception.JeecgSqlInjectionException;
import java.util.*;
import java.util.regex.Matcher;
@ -59,27 +61,33 @@ public abstract class AbstractQueryBlackListHandler {
if(list==null){
return true;
}
log.info("--获取sql信息--", list.toString());
log.info(" 获取sql信息 {} ", list.toString());
boolean flag = checkTableAndFieldsName(list);
if(flag == false){
return false;
}
for (QueryTable table : list) {
String name = table.getName();
String fieldString = ruleMap.get(name);
String fieldRule = ruleMap.get(name);
// 有没有配置这张表
if (fieldString != null) {
if ("*".equals(fieldString) || table.isAll()) {
if (fieldRule != null) {
if ("*".equals(fieldRule) || table.isAll()) {
flag = false;
log.warn("sql黑名单校验表【"+name+"】禁止查询");
break;
} else if (table.existSameField(fieldString)) {
} else if (table.existSameField(fieldRule)) {
flag = false;
break;
}
}
}
// 返回黑名单校验结果(不合法直接抛出异常)
if(!flag){
log.error(this.getError());
throw new JeecgSqlInjectionException(this.getError());
}
return flag;
}
@ -189,21 +197,21 @@ public abstract class AbstractQueryBlackListHandler {
* @return
*/
public boolean existSameField(String fieldString) {
String[] arr = fieldString.split(",");
for (String exp : fields) {
for (String config : arr) {
if (exp.equals(config)) {
String[] controlFields = fieldString.split(",");
for (String sqlField : fields) {
for (String controlField : controlFields) {
if (sqlField.equals(controlField)) {
// 非常明确的列直接比较
log.warn("sql黑名单校验表【"+name+"】中字段【"+config+"】禁止查询");
log.warn("sql黑名单校验表【"+name+"】中字段【"+controlField+"】禁止查询");
return true;
} else {
// 使用表达式的列 只能判读字符串包含了
String aliasColumn = config;
if (alias != null && alias.length() > 0) {
aliasColumn = alias + "." + config;
String aliasColumn = controlField;
if (StringUtils.isNotBlank(alias)) {
aliasColumn = alias + "." + controlField;
}
if (exp.indexOf(aliasColumn) > 0) {
log.warn("sql黑名单校验表【"+name+"】中字段【"+config+"】禁止查询");
if (sqlField.indexOf(aliasColumn) != -1) {
log.warn("sql黑名单校验表【"+name+"】中字段【"+controlField+"】禁止查询");
return true;
}
}

View File

@ -116,7 +116,7 @@ public class Swagger2Config implements WebMvcConfigurer {
// 描述
.description("后台API接口")
// 作者
.contact(new Contact("北京敲敲云科技有限公司","www.jeccg.com","jeecgos@163.com"))
.contact(new Contact("北京国炬信息技术有限公司","www.jeccg.com","jeecgos@163.com"))
.license("The Apache License, Version 2.0")
.licenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html")
.build();

View File

@ -42,7 +42,7 @@ public class SignAuthInterceptor implements HandlerInterceptor {
String xTimestamp = request.getHeader(CommonConstant.X_TIMESTAMP);
if(oConvertUtils.isEmpty(xTimestamp)){
Result<?> result = Result.error("Sign签名校验失败");
Result<?> result = Result.error("Sign签名校验失败,时间戳为空");
log.error("Sign 签名校验失败Header xTimestamp 为空");
//校验失败返回前端
response.setCharacterEncoding("UTF-8");
@ -79,6 +79,7 @@ public class SignAuthInterceptor implements HandlerInterceptor {
log.debug("Sign 签名通过Header Sign : {}",headerSign);
return true;
} else {
log.info("sign allParams: {}", allParams);
log.error("request URI = " + request.getRequestURI());
log.error("Sign 签名校验失败Header Sign : {}",headerSign);
//校验失败返回前端

View File

@ -1,5 +1,12 @@
package org.jeecg.config.sign.util;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.util.oConvertUtils;
import org.springframework.http.HttpMethod;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
@ -10,15 +17,6 @@ import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.util.oConvertUtils;
import org.springframework.http.HttpMethod;
import com.alibaba.fastjson.JSONObject;
/**
* http 工具类 获取请求中的参数
*
@ -43,6 +41,16 @@ public class HttpUtils {
if (pathVariable.contains(SymbolConstant.COMMA)) {
log.info(" pathVariable: {}",pathVariable);
String deString = URLDecoder.decode(pathVariable, "UTF-8");
//https://www.52dianzi.com/category/article/37/565371.html
if(deString.contains("%")){
try {
deString = URLDecoder.decode(deString, "UTF-8");
} catch (Exception e) {
//e.printStackTrace();
}
log.info("存在%情况下,执行两次解码 — pathVariable decode: {}",deString);
}
log.info(" pathVariable decode: {}",deString);
result.put(SignUtil.X_PATH_VARIABLE, deString);
}
@ -81,6 +89,12 @@ public class HttpUtils {
if (pathVariable.contains(SymbolConstant.COMMA)) {
log.info(" pathVariable: {}",pathVariable);
String deString = URLDecoder.decode(pathVariable, "UTF-8");
//https://www.52dianzi.com/category/article/37/565371.html
if(deString.contains("%")){
deString = URLDecoder.decode(deString, "UTF-8");
log.info("存在%情况下,执行两次解码 — pathVariable decode: {}",deString);
}
log.info(" pathVariable decode: {}",deString);
result.put(SignUtil.X_PATH_VARIABLE, deString);
}

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-boot-parent</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.5.3</version>
<version>3.5.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -12,6 +12,8 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.aspect.annotation.PermissionData;
@ -26,6 +28,7 @@ import org.jeecg.modules.demo.test.service.IJeecgDemoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import reactor.core.publisher.Mono;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -468,4 +471,19 @@ public class JeecgDemoController extends JeecgController<JeecgDemo, IJeecgDemoSe
return Result.ok(jeecgDemoService.getCreateByList());
}
/**
* 测试Mono对象
* @return
*/
@ApiOperation("Mono测试")
@GetMapping(value ="/test")
public Mono<String> test() {
//解决shiro报错No SecurityManager accessible to the calling code, either bound to the org.apache.shiro
// https://blog.csdn.net/Japhet_jiu/article/details/131177210
DefaultSecurityManager securityManager = new DefaultSecurityManager();
SecurityUtils.setSecurityManager(securityManager);
return Mono.just("测试");
}
}

View File

@ -7,7 +7,7 @@
select * from demo where name = #{name}
</select>
<!-- 根据权限sql查询数据集 -->
<!-- 根据权限sql查询数据集 20230904 内部写法调用位置installAuthJdbc暂不处理sql注入问题-->
<select id="queryListWithPermission" parameterType="Object" resultType="org.jeecg.modules.demo.test.entity.JeecgDemo">
select * from demo where 1=1 ${permissionSql}
</select>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-system-api</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.5.3</version>
<version>3.5.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -1,40 +0,0 @@
package org.jeecg.common.drag.api;
import org.jeecg.common.constant.ServiceNameConstants;
import org.jeecg.common.drag.api.fallbak.DragBaseApiFallback;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* 仪表盘API接口
*
* @author lsq
* @date 2023/01/09
*/
@Component
@FeignClient(contextId = "dragBaseRemoteApi", value = ServiceNameConstants.SERVICE_SYSTEM, fallbackFactory = DragBaseApiFallback.class)
@ConditionalOnMissingClass("org.jeecg.modules.drag.service.impl.OnlDragBaseApiImpl")
public interface IDragBaseApi {
/**
* 通过id赋值仪表盘数据
*
* @param id
* @return
*/
@GetMapping(value = "/drag/api/copyDragPage")
String copyDragPage( @RequestParam("id") String id);
/**
* 删除表单
* @param id
*/
@DeleteMapping(value = "/drag/api/deleteDragPage")
void deleteDragPage(@RequestParam("id") String id);
}

View File

@ -1,23 +0,0 @@
package org.jeecg.common.drag.api.factory;
import org.jeecg.common.drag.api.IDragBaseApi;
import org.jeecg.common.drag.api.fallbak.DragBaseApiFallback;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
/**
* DragBaseApiFallbackFactory
* @author: lsq
* @date 2023/01/09
*/
@Component
public class DragBaseApiFallbackFactory implements FallbackFactory<IDragBaseApi> {
@Override
public IDragBaseApi create(Throwable throwable) {
DragBaseApiFallback fallback = new DragBaseApiFallback();
fallback.setCause(throwable);
return fallback;
}
}

View File

@ -1,26 +0,0 @@
package org.jeecg.common.drag.api.fallbak;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.drag.api.IDragBaseApi;
/**
* IDragBaseApi fallback
* @author LSQ
* @date 2023/01/09
*/
@Slf4j
public class DragBaseApiFallback implements IDragBaseApi {
@Setter
private Throwable cause;
@Override
public void deleteDragPage(String id) {}
@Override
public String copyDragPage(String id) {
return null;
}
}

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-system-api</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.5.3</version>
<version>3.5.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -1,27 +0,0 @@
package org.jeecg.common.drag.api;
/**
* 仪表盘API接口
* @date 2023/1/9
* @author lsq
*/
public interface IDragBaseApi {
/**
* 通过id删除仪表盘
*
* @param id
* @return
*/
void deleteDragPage(String id);
/**
* 通过id复制仪表盘
*
* @param id
* @return id
*/
String copyDragPage(String id);
}

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-module-system</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.5.3</version>
<version>3.5.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-module-system</artifactId>
<version>3.5.3</version>
<version>3.5.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@ -37,7 +37,7 @@
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>drag-free</artifactId>
<version>1.0.1</version>
<version>1.0.2</version>
</dependency>
<!-- 积木报表 mongo redis 支持包
<dependency>

View File

@ -10,10 +10,12 @@ import org.jeecg.modules.system.service.impl.SysBaseApiImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* 自定义积木报表鉴权(如果不进行自定义,则所有请求不做权限控制)
@ -42,6 +44,16 @@ public class JimuReportTokenService implements JmReportTokenServiceI {
return JwtUtil.getUsername(token);
}
@Override
public String[] getRoles(String token) {
String username = JwtUtil.getUsername(token);
Set roles = sysBaseApi.getUserRoleSet(username);
if(CollectionUtils.isEmpty(roles)){
return null;
}
return (String[]) roles.toArray(new String[roles.size()]);
}
@Override
public Boolean verifyToken(String token) {
return TokenUtils.verifyToken(token, sysBaseApi, redisUtil);

View File

@ -48,7 +48,7 @@ public class OssFileController {
@ResponseBody
@PostMapping("/upload")
//@RequiresRoles("admin")
//@RequiresPermissions("system:ossFile:upload")
@RequiresPermissions("system:ossFile:upload")
public Result upload(@RequestParam("file") MultipartFile multipartFile) {
Result result = new Result();
try {

View File

@ -80,7 +80,7 @@ public class QuartzJobController {
* @return
*/
//@RequiresRoles("admin")
//@RequiresPermissions("system:quartzJob:add")
@RequiresPermissions("system:quartzJob:add")
@RequestMapping(value = "/add", method = RequestMethod.POST)
public Result<?> add(@RequestBody QuartzJob quartzJob) {
quartzJobService.saveAndScheduleJob(quartzJob);
@ -94,7 +94,7 @@ public class QuartzJobController {
* @return
*/
//@RequiresRoles("admin")
//@RequiresPermissions("system:quartzJob:edit")
@RequiresPermissions("system:quartzJob:edit")
@RequestMapping(value = "/edit", method ={RequestMethod.PUT, RequestMethod.POST})
public Result<?> eidt(@RequestBody QuartzJob quartzJob) {
try {
@ -113,7 +113,7 @@ public class QuartzJobController {
* @return
*/
//@RequiresRoles("admin")
//@RequiresPermissions("system:quartzJob:delete")
@RequiresPermissions("system:quartzJob:delete")
@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
QuartzJob quartzJob = quartzJobService.getById(id);
@ -132,7 +132,7 @@ public class QuartzJobController {
* @return
*/
//@RequiresRoles("admin")
//@RequiresPermissions("system:quartzJob:deleteBatch")
@RequiresPermissions("system:quartzJob:deleteBatch")
@RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
if (ids == null || "".equals(ids.trim())) {
@ -152,7 +152,7 @@ public class QuartzJobController {
* @return
*/
//@RequiresRoles("admin")
//@RequiresPermissions("system:quartzJob:pause")
@RequiresPermissions("system:quartzJob:pause")
@GetMapping(value = "/pause")
@ApiOperation(value = "停止定时任务")
public Result<Object> pauseJob(@RequestParam(name = "id") String id) {
@ -171,7 +171,7 @@ public class QuartzJobController {
* @return
*/
//@RequiresRoles("admin")
//@RequiresPermissions("system:quartzJob:resume")
@RequiresPermissions("system:quartzJob:resume")
@GetMapping(value = "/resume")
@ApiOperation(value = "启动定时任务")
public Result<Object> resumeJob(@RequestParam(name = "id") String id) {
@ -272,7 +272,7 @@ public class QuartzJobController {
* @return
*/
//@RequiresRoles("admin")
//@RequiresPermissions("system:quartzJob:execute")
@RequiresPermissions("system:quartzJob:execute")
@GetMapping("/execute")
public Result<?> execute(@RequestParam(name = "id", required = true) String id) {
QuartzJob quartzJob = quartzJobService.getById(id);

View File

@ -1,24 +1,18 @@
package org.jeecg.modules.system.controller;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.util.SqlInjectionUtil;
import org.jeecg.modules.system.mapper.SysDictMapper;
import org.jeecg.modules.system.model.DuplicateCheckVo;
import org.jeecg.modules.system.security.DictQueryBlackListHandler;
import org.mybatis.spring.MyBatisSystemException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.system.model.DuplicateCheckVo;
import org.jeecg.modules.system.service.ISysDictService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
/**
* @Title: DuplicateCheckAction
@ -34,10 +28,7 @@ import lombok.extern.slf4j.Slf4j;
public class DuplicateCheckController {
@Autowired
SysDictMapper sysDictMapper;
@Autowired
DictQueryBlackListHandler dictQueryBlackListHandler;
ISysDictService sysDictService;
/**
* 校验数据是否在系统中是否存在
@ -47,14 +38,9 @@ public class DuplicateCheckController {
@RequestMapping(value = "/check", method = RequestMethod.GET)
@ApiOperation("重复校验接口")
public Result<String> doDuplicateCheck(DuplicateCheckVo duplicateCheckVo, HttpServletRequest request) {
Long num = null;
log.debug("----duplicate check------"+ duplicateCheckVo.toString());
//关联表字典举例sys_user,realname,id
//SQL注入校验只限制非法串改数据库
final String[] sqlInjCheck = {duplicateCheckVo.getTableName(),duplicateCheckVo.getFieldName()};
SqlInjectionUtil.filterContent(sqlInjCheck);
// update-begin-author:taoyan date:20211227 for: JTC-25 【online报表】oracle 操作问题 录入弹框啥都不填直接保存 ①编码不是应该提示必填么?②报错也应该是具体文字提示,不是后台错误日志
// 1.填值为空,直接返回
if(StringUtils.isEmpty(duplicateCheckVo.getFieldVal())){
Result rs = new Result();
rs.setCode(500);
@ -62,31 +48,9 @@ public class DuplicateCheckController {
rs.setMessage("数据为空,不作处理!");
return rs;
}
//update-begin-author:taoyan date:20220329 for: VUEN-223【安全漏洞】当前被攻击的接口
String checkSql = duplicateCheckVo.getTableName() + SymbolConstant.COMMA + duplicateCheckVo.getFieldName() + SymbolConstant.COMMA;
if(!dictQueryBlackListHandler.isPass(checkSql)){
return Result.error(dictQueryBlackListHandler.getError());
}
//update-end-author:taoyan date:20220329 for: VUEN-223【安全漏洞】当前被攻击的接口
// update-end-author:taoyan date:20211227 for: JTC-25 【online报表】oracle 操作问题 录入弹框啥都不填直接保存 ①编码不是应该提示必填么?②报错也应该是具体文字提示,不是后台错误日志
// update-begin-author:liusq date:20230721 for: [issues/5134] duplicate/check Sql泄露问题
try{
if (StringUtils.isNotBlank(duplicateCheckVo.getDataId())) {
// [2].编辑页面校验
num = sysDictMapper.duplicateCheckCountSql(duplicateCheckVo);
} else {
// [1].添加页面校验
num = sysDictMapper.duplicateCheckCountSqlNoDataId(duplicateCheckVo);
}
}catch(MyBatisSystemException e){
log.error(e.getMessage(), e);
String errorCause = "查询异常,请检查唯一校验的配置!";
return Result.error(errorCause);
}
// update-end-author:liusq date:20230721 for: [issues/5134] duplicate/check Sql泄露问题
if (num == null || num == 0) {
// 2.返回结果
if (sysDictService.duplicateCheckData(duplicateCheckVo)) {
// 该值可用
return Result.ok("该值可用!");
} else {
@ -95,21 +59,5 @@ public class DuplicateCheckController {
return Result.error("该值不可用,系统中已存在!");
}
}
/**
* VUEN-2584【issue】平台sql注入漏洞几个问题
* 部分特殊函数 可以将查询结果混夹在错误信息中,导致数据库的信息暴露
* @param e
* @return
*/
@ExceptionHandler(java.sql.SQLException.class)
public Result<?> handleSQLException(Exception e){
String msg = e.getMessage();
String extractvalue = "extractvalue";
String updatexml = "updatexml";
if(msg!=null && (msg.toLowerCase().indexOf(extractvalue)>=0 || msg.toLowerCase().indexOf(updatexml)>=0)){
return Result.error("校验失败sql解析异常");
}
return Result.error("校验失败sql解析异常" + msg);
}
}

View File

@ -286,6 +286,7 @@ public class LoginController {
String orgCode= user.getOrgCode();
//获取登录租户
Integer tenantId = user.getLoginTenantId();
//设置用户登录部门和登录租户
this.sysUserService.updateUserDepart(username, orgCode,tenantId);
SysUser sysUser = sysUserService.getUserByName(username);
JSONObject obj = new JSONObject();
@ -727,8 +728,8 @@ public class LoginController {
if(failTime!=null){
val = Integer.parseInt(failTime.toString());
}
// 1小时
redisUtil.set(key, ++val, 3600);
// 10分钟
redisUtil.set(key, ++val, 10);
}
}

View File

@ -3,9 +3,6 @@ package org.jeecg.modules.system.controller;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.creator.DruidDataSourceCreator;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -14,7 +11,6 @@ import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.config.TenantContext;
@ -65,7 +61,7 @@ public class SysDataSourceController extends JeecgController<SysDataSource, ISys
*/
@AutoLog(value = "多数据源管理-分页列表查询")
@ApiOperation(value = "多数据源管理-分页列表查询", notes = "多数据源管理-分页列表查询")
//@RequiresPermissions("system:datasource:list")
@RequiresPermissions("system:datasource:list")
@GetMapping(value = "/list")
public Result<?> queryPageList(
SysDataSource sysDataSource,

View File

@ -173,7 +173,7 @@ public class SysDepartController {
* @param sysDepart
* @return
*/
//@RequiresPermissions("system:depart:add")
@RequiresPermissions("system:depart:add")
@RequestMapping(value = "/add", method = RequestMethod.POST)
@CacheEvict(value= {CacheConstant.SYS_DEPARTS_CACHE,CacheConstant.SYS_DEPART_IDS_CACHE}, allEntries=true)
public Result<SysDepart> add(@RequestBody SysDepart sysDepart, HttpServletRequest request) {
@ -199,7 +199,7 @@ public class SysDepartController {
* @param sysDepart
* @return
*/
//@RequiresPermissions("system:depart:edit")
@RequiresPermissions("system:depart:edit")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
@CacheEvict(value= {CacheConstant.SYS_DEPARTS_CACHE,CacheConstant.SYS_DEPART_IDS_CACHE}, allEntries=true)
public Result<SysDepart> edit(@RequestBody SysDepart sysDepart, HttpServletRequest request) {
@ -227,7 +227,7 @@ public class SysDepartController {
* @param id
* @return
*/
//@RequiresPermissions("system:depart:delete")
@RequiresPermissions("system:depart:delete")
@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
@CacheEvict(value= {CacheConstant.SYS_DEPARTS_CACHE,CacheConstant.SYS_DEPART_IDS_CACHE}, allEntries=true)
public Result<SysDepart> delete(@RequestParam(name="id",required=true) String id) {
@ -253,7 +253,7 @@ public class SysDepartController {
* @param ids
* @return
*/
//@RequiresPermissions("system:depart:deleteBatch")
@RequiresPermissions("system:depart:deleteBatch")
@RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
@CacheEvict(value= {CacheConstant.SYS_DEPARTS_CACHE,CacheConstant.SYS_DEPART_IDS_CACHE}, allEntries=true)
public Result<SysDepart> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
@ -377,7 +377,7 @@ public class SysDepartController {
* @param response
* @return
*/
//@RequiresPermissions("system:depart:importExcel")
@RequiresPermissions("system:depart:importExcel")
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
@CacheEvict(value= {CacheConstant.SYS_DEPARTS_CACHE,CacheConstant.SYS_DEPART_IDS_CACHE}, allEntries=true)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {

View File

@ -104,7 +104,7 @@ public class SysDepartRoleController extends JeecgController<SysDepartRole, ISys
* @param sysDepartRole
* @return
*/
//@RequiresPermissions("system:depart:role:add")
@RequiresPermissions("system:depart:role:add")
@ApiOperation(value="部门角色-添加", notes="部门角色-添加")
@PostMapping(value = "/add")
public Result<?> add(@RequestBody SysDepartRole sysDepartRole) {
@ -119,7 +119,7 @@ public class SysDepartRoleController extends JeecgController<SysDepartRole, ISys
* @return
*/
@ApiOperation(value="部门角色-编辑", notes="部门角色-编辑")
//@RequiresPermissions("system:depart:role:edit")
@RequiresPermissions("system:depart:role:edit")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
public Result<?> edit(@RequestBody SysDepartRole sysDepartRole) {
sysDepartRoleService.updateById(sysDepartRole);
@ -134,7 +134,7 @@ public class SysDepartRoleController extends JeecgController<SysDepartRole, ISys
*/
@AutoLog(value = "部门角色-通过id删除")
@ApiOperation(value="部门角色-通过id删除", notes="部门角色-通过id删除")
//@RequiresPermissions("system:depart:role:delete")
@RequiresPermissions("system:depart:role:delete")
@DeleteMapping(value = "/delete")
public Result<?> delete(@RequestParam(name="id",required=true) String id) {
sysDepartRoleService.removeById(id);
@ -149,7 +149,7 @@ public class SysDepartRoleController extends JeecgController<SysDepartRole, ISys
*/
@AutoLog(value = "部门角色-批量删除")
@ApiOperation(value="部门角色-批量删除", notes="部门角色-批量删除")
//@RequiresPermissions("system:depart:role:deleteBatch")
@RequiresPermissions("system:depart:role:deleteBatch")
@DeleteMapping(value = "/deleteBatch")
public Result<?> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
this.sysDepartRoleService.removeByIds(Arrays.asList(ids.split(",")));
@ -189,7 +189,7 @@ public class SysDepartRoleController extends JeecgController<SysDepartRole, ISys
* @param json
* @return
*/
//@RequiresPermissions("system:depart:role:userAdd")
@RequiresPermissions("system:depart:role:userAdd")
@RequestMapping(value = "/deptRoleUserAdd", method = RequestMethod.POST)
public Result<?> deptRoleAdd(@RequestBody JSONObject json) {
String newRoleId = json.getString("newRoleId");

View File

@ -391,7 +391,7 @@ public class SysDictController {
* @param sysDict
* @return
*/
//@RequiresPermissions("system:dict:add")
@RequiresPermissions("system:dict:add")
@RequestMapping(value = "/add", method = RequestMethod.POST)
public Result<SysDict> add(@RequestBody SysDict sysDict) {
Result<SysDict> result = new Result<SysDict>();
@ -412,7 +412,7 @@ public class SysDictController {
* @param sysDict
* @return
*/
//@RequiresPermissions("system:dict:edit")
@RequiresPermissions("system:dict:edit")
@RequestMapping(value = "/edit", method = { RequestMethod.PUT,RequestMethod.POST })
public Result<SysDict> edit(@RequestBody SysDict sysDict) {
Result<SysDict> result = new Result<SysDict>();
@ -434,7 +434,7 @@ public class SysDictController {
* @param id
* @return
*/
//@RequiresPermissions("system:dict:delete")
@RequiresPermissions("system:dict:delete")
@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
@CacheEvict(value={CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries=true)
public Result<SysDict> delete(@RequestParam(name="id",required=true) String id) {
@ -453,7 +453,7 @@ public class SysDictController {
* @param ids
* @return
*/
//@RequiresPermissions("system:dict:deleteBatch")
@RequiresPermissions("system:dict:deleteBatch")
@RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
@CacheEvict(value= {CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries=true)
public Result<SysDict> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
@ -554,7 +554,7 @@ public class SysDictController {
* @param
* @return
*/
//@RequiresPermissions("system:dict:importExcel")
@RequiresPermissions("system:dict:importExcel")
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;

View File

@ -74,7 +74,7 @@ public class SysDictItemController {
* @功能:新增
* @return
*/
//@RequiresPermissions("system:dict:item:add")
@RequiresPermissions("system:dict:item:add")
@RequestMapping(value = "/add", method = RequestMethod.POST)
@CacheEvict(value= {CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries=true)
public Result<SysDictItem> add(@RequestBody SysDictItem sysDictItem) {
@ -95,7 +95,7 @@ public class SysDictItemController {
* @param sysDictItem
* @return
*/
//@RequiresPermissions("system:dict:item:edit")
@RequiresPermissions("system:dict:item:edit")
@RequestMapping(value = "/edit", method = { RequestMethod.PUT,RequestMethod.POST })
@CacheEvict(value={CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries=true)
public Result<SysDictItem> edit(@RequestBody SysDictItem sysDictItem) {
@ -119,7 +119,7 @@ public class SysDictItemController {
* @param id
* @return
*/
//@RequiresPermissions("system:dict:item:delete")
@RequiresPermissions("system:dict:item:delete")
@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
@CacheEvict(value={CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries=true)
public Result<SysDictItem> delete(@RequestParam(name="id",required=true) String id) {
@ -141,7 +141,7 @@ public class SysDictItemController {
* @param ids
* @return
*/
//@RequiresPermissions("system:dict:item:deleteBatch")
@RequiresPermissions("system:dict:item:deleteBatch")
@RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
@CacheEvict(value={CacheConstant.SYS_DICT_CACHE, CacheConstant.SYS_ENABLE_DICT_CACHE}, allEntries=true)
public Result<SysDictItem> deleteBatch(@RequestParam(name="ids",required=true) String ids) {

View File

@ -68,7 +68,7 @@ public class SysGatewayRouteController extends JeecgController<SysGatewayRoute,
* @param id
* @return
*/
//@RequiresPermissions("system:getway:delete")
@RequiresPermissions("system:getway:delete")
@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
sysGatewayRouteService.deleteById(id);

View File

@ -360,7 +360,7 @@ public class SysPermissionController {
* @param permission
* @return
*/
//@RequiresPermissions("system:permission:add")
@RequiresPermissions("system:permission:add")
@RequestMapping(value = "/add", method = RequestMethod.POST)
public Result<SysPermission> add(@RequestBody SysPermission permission) {
Result<SysPermission> result = new Result<SysPermission>();
@ -380,7 +380,7 @@ public class SysPermissionController {
* @param permission
* @return
*/
//@RequiresPermissions("system:permission:edit")
@RequiresPermissions("system:permission:edit")
@RequestMapping(value = "/edit", method = { RequestMethod.PUT, RequestMethod.POST })
public Result<SysPermission> edit(@RequestBody SysPermission permission) {
Result<SysPermission> result = new Result<>();
@ -422,7 +422,7 @@ public class SysPermissionController {
* @param id
* @return
*/
//@RequiresPermissions("system:permission:delete")
@RequiresPermissions("system:permission:delete")
@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
public Result<SysPermission> delete(@RequestParam(name = "id", required = true) String id) {
Result<SysPermission> result = new Result<>();
@ -441,7 +441,7 @@ public class SysPermissionController {
* @param ids
* @return
*/
//@RequiresPermissions("system:permission:deleteBatch")
@RequiresPermissions("system:permission:deleteBatch")
@RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
public Result<SysPermission> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
Result<SysPermission> result = new Result<>();
@ -548,7 +548,7 @@ public class SysPermissionController {
*
* @return
*/
//@RequiresPermissions("system:permission:saveRole")
@RequiresPermissions("system:permission:saveRole")
@RequestMapping(value = "/saveRolePermission", method = RequestMethod.POST)
public Result<String> saveRolePermission(@RequestBody JSONObject json) {
long start = System.currentTimeMillis();
@ -877,7 +877,7 @@ public class SysPermissionController {
* @param sysPermissionDataRule
* @return
*/
//@RequiresPermissions("system:permission:addRule")
@RequiresPermissions("system:permission:addRule")
@RequestMapping(value = "/addPermissionRule", method = RequestMethod.POST)
public Result<SysPermissionDataRule> addPermissionRule(@RequestBody SysPermissionDataRule sysPermissionDataRule) {
Result<SysPermissionDataRule> result = new Result<SysPermissionDataRule>();
@ -892,7 +892,7 @@ public class SysPermissionController {
return result;
}
//@RequiresPermissions("system:permission:editRule")
@RequiresPermissions("system:permission:editRule")
@RequestMapping(value = "/editPermissionRule", method = { RequestMethod.PUT, RequestMethod.POST })
public Result<SysPermissionDataRule> editPermissionRule(@RequestBody SysPermissionDataRule sysPermissionDataRule) {
Result<SysPermissionDataRule> result = new Result<SysPermissionDataRule>();
@ -912,7 +912,7 @@ public class SysPermissionController {
* @param id
* @return
*/
//@RequiresPermissions("system:permission:deleteRule")
@RequiresPermissions("system:permission:deleteRule")
@RequestMapping(value = "/deletePermissionRule", method = RequestMethod.DELETE)
public Result<SysPermissionDataRule> deletePermissionRule(@RequestParam(name = "id", required = true) String id) {
Result<SysPermissionDataRule> result = new Result<SysPermissionDataRule>();
@ -969,7 +969,7 @@ public class SysPermissionController {
* @return
*/
@RequestMapping(value = "/saveDepartPermission", method = RequestMethod.POST)
//@RequiresPermissions("system:permission:saveDepart")
@RequiresPermissions("system:permission:saveDepart")
public Result<String> saveDepartPermission(@RequestBody JSONObject json) {
long start = System.currentTimeMillis();
Result<String> result = new Result<>();

View File

@ -136,7 +136,7 @@ public class SysRoleController {
* @return
*/
@RequestMapping(value = "/add", method = RequestMethod.POST)
//@RequiresPermissions("system:role:add")
@RequiresPermissions("system:role:add")
public Result<SysRole> add(@RequestBody SysRole role) {
Result<SysRole> result = new Result<SysRole>();
try {
@ -155,7 +155,7 @@ public class SysRoleController {
* @param role
* @return
*/
//@RequiresPermissions("system:role:edit")
@RequiresPermissions("system:role:edit")
@RequestMapping(value = "/edit",method = {RequestMethod.PUT,RequestMethod.POST})
public Result<SysRole> edit(@RequestBody SysRole role) {
Result<SysRole> result = new Result<SysRole>();
@ -179,7 +179,7 @@ public class SysRoleController {
* @param id
* @return
*/
//@RequiresPermissions("system:role:delete")
@RequiresPermissions("system:role:delete")
@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
public Result<?> delete(@RequestParam(name="id",required=true) String id) {
sysRoleService.deleteRole(id);
@ -191,7 +191,7 @@ public class SysRoleController {
* @param ids
* @return
*/
//@RequiresPermissions("system:role:deleteBatch")
@RequiresPermissions("system:role:deleteBatch")
@RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
public Result<SysRole> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
Result<SysRole> result = new Result<SysRole>();
@ -252,7 +252,7 @@ public class SysRoleController {
*
* @return
*/
//@RequiresPermissions("system:role:queryallNoByTenant")
@RequiresPermissions("system:role:queryallNoByTenant")
@RequestMapping(value = "/queryallNoByTenant", method = RequestMethod.GET)
public Result<List<SysRole>> queryallNoByTenant() {
Result<List<SysRole>> result = new Result<>();

View File

@ -67,7 +67,7 @@ public class SysRoleIndexController extends JeecgController<SysRoleIndex, ISysRo
* @param sysRoleIndex
* @return
*/
//@RequiresPermissions("system:roleindex:add")
@RequiresPermissions("system:roleindex:add")
@AutoLog(value = "角色首页配置-添加")
@ApiOperation(value = "角色首页配置-添加", notes = "角色首页配置-添加")
@PostMapping(value = "/add")
@ -83,7 +83,7 @@ public class SysRoleIndexController extends JeecgController<SysRoleIndex, ISysRo
* @param sysRoleIndex
* @return
*/
//@RequiresPermissions("system:roleindex:edit")
@RequiresPermissions("system:roleindex:edit")
@AutoLog(value = "角色首页配置-编辑")
@ApiOperation(value = "角色首页配置-编辑", notes = "角色首页配置-编辑")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT, RequestMethod.POST})

View File

@ -69,7 +69,7 @@ public class SysTenantController {
* @param req
* @return
*/
//@RequiresPermissions("system:tenant:list")
@RequiresPermissions("system:tenant:list")
@PermissionData(pageComponent = "system/TenantList")
@RequestMapping(value = "/list", method = RequestMethod.GET)
public Result<IPage<SysTenant>> queryPageList(SysTenant sysTenant, @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@ -108,7 +108,7 @@ public class SysTenantController {
* @return
*/
@GetMapping("/recycleBinPageList")
//@RequiresPermissions("system:tenant:recycleBinPageList")
@RequiresPermissions("system:tenant:recycleBinPageList")
public Result<IPage<SysTenant>> recycleBinPageList(SysTenant sysTenant, @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize, HttpServletRequest req){
Result<IPage<SysTenant>> result = new Result<IPage<SysTenant>>();
@ -124,7 +124,7 @@ public class SysTenantController {
* @param
* @return
*/
//@RequiresPermissions("system:tenant:add")
@RequiresPermissions("system:tenant:add")
@RequestMapping(value = "/add", method = RequestMethod.POST)
public Result<SysTenant> add(@RequestBody SysTenant sysTenant) {
Result<SysTenant> result = new Result();
@ -146,7 +146,7 @@ public class SysTenantController {
* @param
* @return
*/
//@RequiresPermissions("system:tenant:edit")
@RequiresPermissions("system:tenant:edit")
@RequestMapping(value = "/edit", method ={RequestMethod.PUT, RequestMethod.POST})
public Result<SysTenant> edit(@RequestBody SysTenant tenant) {
Result<SysTenant> result = new Result();
@ -169,7 +169,7 @@ public class SysTenantController {
* @param id
* @return
*/
//@RequiresPermissions("system:tenant:delete")
@RequiresPermissions("system:tenant:delete")
@RequestMapping(value = "/delete", method ={RequestMethod.DELETE, RequestMethod.POST})
public Result<?> delete(@RequestParam(name="id",required=true) String id) {
//------------------------------------------------------------------
@ -197,7 +197,7 @@ public class SysTenantController {
* @param ids
* @return
*/
//@RequiresPermissions("system:tenant:deleteBatch")
@RequiresPermissions("system:tenant:deleteBatch")
@RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
public Result<?> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
Result<?> result = new Result<>();
@ -281,7 +281,7 @@ public class SysTenantController {
* 查询有效的 租户数据
* @return
*/
//@RequiresPermissions("system:tenant:queryList")
@RequiresPermissions("system:tenant:queryList")
@RequestMapping(value = "/queryList", method = RequestMethod.GET)
public Result<List<SysTenant>> queryList(@RequestParam(name="ids",required=false) String ids) {
Result<List<SysTenant>> result = new Result<List<SysTenant>>();
@ -307,7 +307,7 @@ public class SysTenantController {
* @return
*/
@GetMapping(value = "/packList")
//@RequiresPermissions("system:tenant:packList")
@RequiresPermissions("system:tenant:packList")
public Result<IPage<SysTenantPack>> queryPackPageList(SysTenantPack sysTenantPack,
@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
@ -329,7 +329,7 @@ public class SysTenantController {
* @return
*/
@PostMapping(value = "/addPackPermission")
//@RequiresPermissions("system:tenant:add:pack")
@RequiresPermissions("system:tenant:add:pack")
public Result<String> addPackPermission(@RequestBody SysTenantPack sysTenantPack) {
sysTenantPackService.addPackPermission(sysTenantPack);
return Result.ok("创建租户产品包成功");
@ -342,7 +342,7 @@ public class SysTenantController {
* @return
*/
@PutMapping(value = "/editPackPermission")
//@RequiresPermissions("system:tenant:edit:pack")
@RequiresPermissions("system:tenant:edit:pack")
public Result<String> editPackPermission(@RequestBody SysTenantPack sysTenantPack) {
sysTenantPackService.editPackPermission(sysTenantPack);
return Result.ok("修改租户产品包成功");
@ -355,7 +355,7 @@ public class SysTenantController {
* @return
*/
@DeleteMapping("/deletePackPermissions")
//@RequiresPermissions("system:tenant:delete:pack")
@RequiresPermissions("system:tenant:delete:pack")
public Result<String> deletePackPermissions(@RequestParam(value = "ids") String ids) {
sysTenantPackService.deletePackPermissions(ids);
return Result.ok("删除租户产品包成功");
@ -398,7 +398,7 @@ public class SysTenantController {
* @return
*/
@PutMapping("/invitationUserJoin")
//@RequiresPermissions("system:tenant:invitation:user")
@RequiresPermissions("system:tenant:invitation:user")
public Result<String> invitationUserJoin(@RequestParam("ids") String ids, @RequestParam("phone") String phone){
sysTenantService.invitationUserJoin(ids,phone);
return Result.ok("邀请用户成功");
@ -413,7 +413,7 @@ public class SysTenantController {
* @return
*/
@RequestMapping(value = "/getTenantUserList", method = RequestMethod.GET)
//@RequiresPermissions("system:tenant:user:list")
@RequiresPermissions("system:tenant:user:list")
public Result<IPage<SysUser>> getTenantUserList(SysUser user,
@RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
@RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
@ -434,7 +434,7 @@ public class SysTenantController {
* @return
*/
@PutMapping("/leaveTenant")
//@RequiresPermissions("system:tenant:leave")
@RequiresPermissions("system:tenant:leave")
public Result<String> leaveTenant(@RequestParam("userIds") String userIds,
@RequestParam("tenantId") String tenantId){
Result<String> result = new Result<>();
@ -541,7 +541,7 @@ public class SysTenantController {
* @return
*/
@GetMapping("/getUserTenantPageList")
//@RequiresPermissions("system:tenant:tenantPageList")
@RequiresPermissions("system:tenant:tenantPageList")
public Result<IPage<SysUserTenantVo>> getUserTenantPageList(@RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
@RequestParam(name = "userTenantStatus") String userTenantStatus,
@ -653,7 +653,7 @@ public class SysTenantController {
* @return
*/
@DeleteMapping("/deleteLogicDeleted")
//@RequiresPermissions("system:tenant:deleteTenantLogic")
@RequiresPermissions("system:tenant:deleteTenantLogic")
public Result<String> deleteTenantLogic(@RequestParam("ids") String ids){
sysTenantService.deleteTenantLogic(ids);
return Result.ok("彻底删除成功");
@ -665,7 +665,7 @@ public class SysTenantController {
* @return
*/
@PutMapping("/revertTenantLogic")
//@RequiresPermissions("system:tenant:revertTenantLogic")
@RequiresPermissions("system:tenant:revertTenantLogic")
public Result<String> revertTenantLogic(@RequestParam("ids") String ids){
sysTenantService.revertTenantLogic(ids);
return Result.ok("还原成功");

View File

@ -140,7 +140,7 @@ public class SysUserController {
* @param req
* @return
*/
//@RequiresPermissions("system:user:listAll")
@RequiresPermissions("system:user:listAll")
@RequestMapping(value = "/listAll", method = RequestMethod.GET)
public Result<IPage<SysUser>> queryAllPageList(SysUser user, @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
@RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize, HttpServletRequest req) {
@ -148,7 +148,7 @@ public class SysUserController {
return sysUserService.queryPageList(req, queryWrapper, pageSize, pageNo);
}
//@RequiresPermissions("system:user:add")
@RequiresPermissions("system:user:add")
@RequestMapping(value = "/add", method = RequestMethod.POST)
public Result<SysUser> add(@RequestBody JSONObject jsonObject) {
Result<SysUser> result = new Result<SysUser>();
@ -178,7 +178,7 @@ public class SysUserController {
return result;
}
//@RequiresPermissions("system:user:edit")
@RequiresPermissions("system:user:edit")
@RequestMapping(value = "/edit", method = {RequestMethod.PUT,RequestMethod.POST})
public Result<SysUser> edit(@RequestBody JSONObject jsonObject) {
Result<SysUser> result = new Result<SysUser>();
@ -216,7 +216,7 @@ public class SysUserController {
/**
* 删除用户
*/
//@RequiresPermissions("system:user:delete")
@RequiresPermissions("system:user:delete")
@RequestMapping(value = "/delete", method = RequestMethod.DELETE)
public Result<?> delete(@RequestParam(name="id",required=true) String id) {
baseCommonService.addLog("删除用户id " +id ,CommonConstant.LOG_TYPE_2, 3);
@ -227,7 +227,7 @@ public class SysUserController {
/**
* 批量删除用户
*/
//@RequiresPermissions("system:user:deleteBatch")
@RequiresPermissions("system:user:deleteBatch")
@RequestMapping(value = "/deleteBatch", method = RequestMethod.DELETE)
public Result<?> deleteBatch(@RequestParam(name="ids",required=true) String ids) {
baseCommonService.addLog("批量删除用户, ids " +ids ,CommonConstant.LOG_TYPE_2, 3);
@ -240,7 +240,7 @@ public class SysUserController {
* @param jsonObject
* @return
*/
//@RequiresPermissions("system:user:frozenBatch")
@RequiresPermissions("system:user:frozenBatch")
@RequestMapping(value = "/frozenBatch", method = RequestMethod.PUT)
public Result<SysUser> frozenBatch(@RequestBody JSONObject jsonObject) {
Result<SysUser> result = new Result<SysUser>();
@ -263,7 +263,7 @@ public class SysUserController {
}
//@RequiresPermissions("system:user:queryById")
@RequiresPermissions("system:user:queryById")
@RequestMapping(value = "/queryById", method = RequestMethod.GET)
public Result<SysUser> queryById(@RequestParam(name = "id", required = true) String id) {
Result<SysUser> result = new Result<SysUser>();
@ -277,7 +277,7 @@ public class SysUserController {
return result;
}
//@RequiresPermissions("system:user:queryUserRole")
@RequiresPermissions("system:user:queryUserRole")
@RequestMapping(value = "/queryUserRole", method = RequestMethod.GET)
public Result<List<String>> queryUserRole(@RequestParam(name = "userid", required = true) String userid) {
Result<List<String>> result = new Result<>();
@ -330,7 +330,7 @@ public class SysUserController {
/**
* 修改密码
*/
//@RequiresPermissions("system:user:changepwd")
@RequiresPermissions("system:user:changepwd")
@RequestMapping(value = "/changePassword", method = RequestMethod.PUT)
public Result<?> changePassword(@RequestBody SysUser sysUser) {
SysUser u = this.sysUserService.getOne(new LambdaQueryWrapper<SysUser>().eq(SysUser::getUsername, sysUser.getUsername()));
@ -453,7 +453,7 @@ public class SysUserController {
* @param request
* @param sysUser
*/
//@RequiresPermissions("system:user:export")
@RequiresPermissions("system:user:export")
@RequestMapping(value = "/exportXls")
public ModelAndView exportXls(SysUser sysUser,HttpServletRequest request) {
// Step.1 组装查询条件
@ -486,7 +486,7 @@ public class SysUserController {
* @param response
* @return
*/
//@RequiresPermissions("system:user:import")
@RequiresPermissions("system:user:import")
@RequestMapping(value = "/importExcel", method = RequestMethod.POST)
public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response)throws IOException {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
@ -600,7 +600,7 @@ public class SysUserController {
/**
* 首页用户重置密码
*/
//@RequiresPermissions("system:user:updatepwd")
@RequiresPermissions("system:user:updatepwd")
@RequestMapping(value = "/updatePassword", method = RequestMethod.PUT)
public Result<?> updatePassword(@RequestBody JSONObject json) {
String username = json.getString("username");
@ -641,7 +641,7 @@ public class SysUserController {
* @param
* @return
*/
//@RequiresPermissions("system:user:addUserRole")
@RequiresPermissions("system:user:addUserRole")
@RequestMapping(value = "/addSysUserRole", method = RequestMethod.POST)
public Result<String> addSysUserRole(@RequestBody SysUserRoleVO sysUserRoleVO) {
Result<String> result = new Result<String>();
@ -672,7 +672,7 @@ public class SysUserController {
* @param
* @return
*/
//@RequiresPermissions("system:user:deleteRole")
@RequiresPermissions("system:user:deleteRole")
@RequestMapping(value = "/deleteUserRole", method = RequestMethod.DELETE)
public Result<SysUserRole> deleteUserRole(@RequestParam(name="roleId") String roleId,
@RequestParam(name="userId",required=true) String userId
@ -696,7 +696,7 @@ public class SysUserController {
* @param
* @return
*/
//@RequiresPermissions("system:user:deleteRoleBatch")
@RequiresPermissions("system:user:deleteRoleBatch")
@RequestMapping(value = "/deleteUserRoleBatch", method = RequestMethod.DELETE)
public Result<SysUserRole> deleteUserRoleBatch(
@RequestParam(name="roleId") String roleId,
@ -827,7 +827,7 @@ public class SysUserController {
/**
* 给指定部门添加对应的用户
*/
//@RequiresPermissions("system:user:editDepartWithUser")
@RequiresPermissions("system:user:editDepartWithUser")
@RequestMapping(value = "/editSysDepartWithUser", method = RequestMethod.POST)
public Result<String> editSysDepartWithUser(@RequestBody SysDepartUsersVO sysDepartUsersVO) {
Result<String> result = new Result<String>();
@ -856,7 +856,7 @@ public class SysUserController {
/**
* 删除指定机构的用户关系
*/
//@RequiresPermissions("system:user:deleteUserInDepart")
@RequiresPermissions("system:user:deleteUserInDepart")
@RequestMapping(value = "/deleteUserInDepart", method = RequestMethod.DELETE)
public Result<SysUserDepart> deleteUserInDepart(@RequestParam(name="depId") String depId,
@RequestParam(name="userId",required=true) String userId
@ -888,7 +888,7 @@ public class SysUserController {
/**
* 批量删除指定机构的用户关系
*/
//@RequiresPermissions("system:user:deleteUserInDepartBatch")
@RequiresPermissions("system:user:deleteUserInDepartBatch")
@RequestMapping(value = "/deleteUserInDepartBatch", method = RequestMethod.DELETE)
public Result<SysUserDepart> deleteUserInDepartBatch(
@RequestParam(name="depId") String depId,
@ -1263,7 +1263,7 @@ public class SysUserController {
* @param userIds 被删除的用户ID多个id用半角逗号分割
* @return
*/
//@RequiresPermissions("system:user:deleteRecycleBin")
@RequiresPermissions("system:user:deleteRecycleBin")
@RequestMapping(value = "/deleteRecycleBin", method = RequestMethod.DELETE)
public Result deleteRecycleBin(@RequestParam("userIds") String userIds) {
if (StringUtils.isNotBlank(userIds)) {
@ -1640,7 +1640,7 @@ public class SysUserController {
* @return
*/
@PostMapping("/login/setting/userEdit")
//@RequiresPermissions("system:user:setting:edit")
@RequiresPermissions("system:user:setting:edit")
public Result<String> userEdit(@RequestBody SysUser sysUser, HttpServletRequest request) {
String username = JwtUtil.getUserNameByToken(request);
SysUser user = sysUserService.getById(sysUser.getId());

View File

@ -66,27 +66,6 @@ public interface SysDictMapper extends BaseMapper<SysDict> {
*/
public List<DictModelMany> queryDictItemsByCodeList(@Param("dictCodeList") List<String> dictCodeList);
/**
* 通过查询指定table的 text code 获取字典
* @param table
* @param text
* @param code
* @return List<DictModel>
*/
@Deprecated
public List<DictModel> queryTableDictItemsByCode(@Param("table") String table,@Param("text") String text,@Param("code") String code);
/**
* 通过查询指定table的 text code 获取字典(指定查询条件)
* @param table
* @param text
* @param code
* @param filterSql
* @return List<DictModel>
*/
@Deprecated
public List<DictModel> queryTableDictItemsByCodeAndFilter(@Param("table") String table,@Param("text") String text,@Param("code") String code,@Param("filterSql") String filterSql);
/**
* 通过查询指定table的 text code 获取字典
* @param table
@ -114,40 +93,6 @@ public interface SysDictMapper extends BaseMapper<SysDict> {
*/
List<DictModelMany> queryManyDictByKeys(@Param("dictCodeList") List<String> dictCodeList, @Param("keys") List<String> keys);
/**
* 通过查询指定table的 text code key 获取字典值
* @param table
* @param text
* @param code
* @param key
* @return String
*/
@Deprecated
public String queryTableDictTextByKey(@Param("table") String table,@Param("text") String text,@Param("code") String code,@Param("key") String key);
// /**
// * 通过查询指定table的 text code key 获取字典值,可批量查询
// *
// * @param table
// * @param text
// * @param code
// * @param keys
// * @return
// */
// @Deprecated
// List<DictModel> queryTableDictTextByKeys(@Param("table") String table, @Param("text") String text, @Param("code") String code, @Param("keys") List<String> keys);
// D /**
//// * 通过查询指定table的 text code key 获取字典值包含value
//// * @param table
//// * @param text
//// * @param code
//// * @param keyArray
//// * @return List<DictModel>
//// */
//// @Deprecated
//// public List<DictModel> queryTableictByKeys(@Param("table") String table, @Param("text") String text, @Param("code") String code, @Param("keyArray") String[] keyArray);
/**
* 查询所有部门 作为字典信息 id -->value,departName -->text
* @return
@ -160,29 +105,6 @@ public interface SysDictMapper extends BaseMapper<SysDict> {
*/
public List<DictModel> queryAllUserBackDictModel();
// /**
// * 通过关键字查询出字典表
// * @param table
// * @param text
// * @param code
// * @param keyword
// * @return
// */
// @Deprecated
// public List<DictModel> queryTableDictItems(@Param("table") String table,@Param("text") String text,@Param("code") String code,@Param("keyword") String keyword);
// /**
// * 通过关键字查询出字典表
// * @param page
// * @param table
// * @param text
// * @param code
// * @param keyword
// * @return
// */
// //IPage<DictModel> queryTableDictItems(Page<DictModel> page, @Param("table") String table, @Param("text") String text, @Param("code") String code, @Param("keyword") String keyword);
/**
* 根据表名、显示字段名、存储字段名 查询树
* @param table
@ -195,7 +117,7 @@ public interface SysDictMapper extends BaseMapper<SysDict> {
* @return
*/
@Deprecated
List<TreeSelectModel> queryTreeList(@Param("query") Map<String, String> query,@Param("table") String table,@Param("text") String text,@Param("code") String code,@Param("pidField") String pidField,@Param("pid") String pid,@Param("hasChildField") String hasChildField,@Param("converIsLeafVal") int converIsLeafVal);
List<TreeSelectModel> queryTreeList(@Param("query") Map<String, String> query, @Param("table") String table, @Param("text") String text, @Param("code") String code, @Param("pidField") String pidField, @Param("pid") String pid, @Param("hasChildField") String hasChildField, @Param("converIsLeafVal") int converIsLeafVal);
/**
* 删除
@ -240,7 +162,7 @@ public interface SysDictMapper extends BaseMapper<SysDict> {
* @return
*/
@Deprecated
IPage<DictModel> queryTableDictWithFilter(Page<DictModel> page, @Param("table") String table, @Param("text") String text, @Param("code") String code, @Param("filterSql") String filterSql);
IPage<DictModel> queryPageTableDictWithFilter(Page<DictModel> page, @Param("table") String table, @Param("text") String text, @Param("code") String code, @Param("filterSql") String filterSql);
/**
* 查询 字典表数据 支持查询条件 查询所有
@ -251,7 +173,7 @@ public interface SysDictMapper extends BaseMapper<SysDict> {
* @return
*/
@Deprecated
List<DictModel> queryAllTableDictItems(@Param("table") String table, @Param("text") String text, @Param("code") String code, @Param("filterSql") String filterSql);
List<DictModel> queryTableDictWithFilter(@Param("table") String table, @Param("text") String text, @Param("code") String code, @Param("filterSql") String filterSql);
/**
* 查询字典表的数据
@ -262,7 +184,9 @@ public interface SysDictMapper extends BaseMapper<SysDict> {
* @param codeValues 存储字段值 作为查询条件in
* @return
*/
List<DictModel> queryTableDictByKeysAndFilterSql(@Param("table") String table, @Param("text") String text, @Param("code") String code, @Param("filterSql") String filterSql, @Param("codeValues") List<String> codeValues);
@Deprecated
List<DictModel> queryTableDictByKeysAndFilterSql(@Param("table") String table, @Param("text") String text, @Param("code") String code, @Param("filterSql") String filterSql,
@Param("codeValues") List<String> codeValues);
/**
* 根据应用id获取字典列表和详情

View File

@ -62,71 +62,35 @@
)
</select>
<!--通过查询指定table的 text code 获取字典-->
<select id="queryTableDictItemsByCode" parameterType="String" resultType="org.jeecg.common.system.vo.DictModel">
select ${text} as "text",${code} as "value" from ${table}
</select>
<!--通过查询指定table的 text code 获取字典(指定查询条件)-->
<select id="queryTableDictItemsByCodeAndFilter" parameterType="String" resultType="org.jeecg.common.system.vo.DictModel">
select ${text} as "text",${code} as "value" from ${table}
<if test="filterSql != null and filterSql != ''">
where ${filterSql}
</if>
</select>
<!--通过查询指定table的 text code key 获取字典值-->
<select id="queryTableDictTextByKey" parameterType="String" resultType="String">
select ${text} as "text" from ${table} where ${code}= #{key}
</select>
<!--通过查询指定table的 text code key 获取字典值,可批量查询
<select id="queryTableDictTextByKeys" parameterType="String" resultType="org.jeecg.common.system.vo.DictModel">
select ${text} as "text", ${code} as "value" from ${table} where ${code} IN (
<foreach item="key" collection="keys" separator=",">
#{key}
</foreach>
)
</select>-->
<!--通过查询指定table的 text code key 获取字典值包含value
<select id="queryTableDictByKeys" parameterType="String" resultType="org.jeecg.common.system.vo.DictModel">
select ${text} as "text", ${code} as "value" from ${table} where ${code} in
<foreach item="key" collection="keyArray" open="(" separator="," close=")">
#{key}
</foreach>
</select>-->
<!-- 重复校验 sql语句 -->
<select id="duplicateCheckCountSql" resultType="Long" parameterType="org.jeecg.modules.system.model.DuplicateCheckVo">
SELECT COUNT(*) FROM ${tableName} WHERE ${fieldName} = #{fieldVal} and id &lt;&gt; #{dataId}
</select>
<!-- 重复校验 sql语句 -->
<select id="duplicateCheckCountSqlNoDataId" resultType="Long" parameterType="org.jeecg.modules.system.model.DuplicateCheckVo">
SELECT COUNT(*) FROM ${tableName} WHERE ${fieldName} = #{fieldVal}
</select>
<!-- 查询部门信息 作为字典数据 -->
<select id="queryAllDepartBackDictModel" resultType="org.jeecg.common.system.vo.DictModel">
select id as "value",depart_name as "text" from sys_depart where del_flag = '0'
</select>
<!-- 查询用户信息 作为字典数据 -->
<!-- 查询用户信息 作为字典数据 -->
<select id="queryAllUserBackDictModel" resultType="org.jeecg.common.system.vo.DictModel">
select username as "value",realname as "text" from sys_user where del_flag = '0'
</select>
<!--通过查询指定table的 text code 获取字典数据,且支持关键字查询
<select id="queryTableDictItems" parameterType="String" resultType="org.jeecg.common.system.vo.DictModel">
select ${text} as "text",${code} as "value" from ${table} where ${text} like #{keyword}
</select> -->
<!-- 根据表名、显示字段名、存储字段名、父ID查询树 -->
<!-- *****************以下方法写法存在SQL注入风险***************** -->
<!-- 重复校验 sql语句【已加入SQL注入check】 -->
<sql id="checkDuplicateCountSqlFragment">
SELECT COUNT(1) FROM ${tableName} WHERE ${fieldName} = #{fieldVal}
</sql>
<select id="duplicateCheckCountSql" resultType="Long" parameterType="org.jeecg.modules.system.model.DuplicateCheckVo">
<include refid="checkDuplicateCountSqlFragment"></include>
AND id &lt;&gt; #{dataId}
</select>
<select id="duplicateCheckCountSqlNoDataId" resultType="Long" parameterType="org.jeecg.modules.system.model.DuplicateCheckVo">
<include refid="checkDuplicateCountSqlFragment"></include>
</select>
<!-- 根据表名、显示字段名、存储字段名、父ID查询树 【已加入SQL注入check】 -->
<select id="queryTreeList" parameterType="Object" resultType="org.jeecg.modules.system.model.TreeSelectModel">
select ${text} as "title",
${code} as "key",
<!-- udapte-begin-author:taoyan date:20211115 for: 自定义树控件只显示父节点,子节点无法展开 (此处还原不可再改) /issues/I4HZAL -->
<if test="hasChildField != null and hasChildField != ''">
<choose>
<when test="converIsLeafVal!=null and converIsLeafVal==1">
@ -137,11 +101,10 @@
</otherwise>
</choose>
</if>
<!-- udapte-end-author:taoyan date:20211115 for: 自定义树控件只显示父节点,子节点无法展开 (此处还原不可再改) /issues/I4HZAL -->
${pidField} as parentId
from ${table}
where
<!-- udapte-begin-author:sunjianlei date:20220110 for: 【JTC-597】自定义树查询条件查不出数据 -->
<!-- 父ID条件 -->
<if test="query == null">
<choose>
<when test="pid != null and pid != ''">
@ -152,6 +115,7 @@
</otherwise>
</choose>
</if>
<!-- 查询条件组装 -->
<if test="query!= null">
1 = 1
<foreach collection="query.entrySet()" item="value" index="key" >
@ -164,7 +128,7 @@
</otherwise>
</choose>
</foreach>
<!-- udapte-end-author:sunjianlei date:20220615 for: 【issues/3709】自定义树查询条件没有处理父ID没有树状结构了 -->
<!-- 【issues/3709】自定义树查询条件没有处理父ID没有树状结构了 -->
<choose>
<when test="pid != null and pid != ''">
and ${pidField} = #{pid}
@ -173,45 +137,42 @@
and (${pidField} = '' OR ${pidField} IS NULL)
</otherwise>
</choose>
<!-- udapte-end-author:sunjianlei date:20220615 for: 【issues/3709】自定义树查询条件没有处理父ID没有树状结构了 -->
</if>
<!-- udapte-end-author:sunjianlei date:20220110 for: 【JTC-597】自定义树查询条件查不出数据 -->
</select>
<!-- 分页查询字典表数据 -->
<!-- 分页查询字典表数据支持text或code模糊查询匹配【已加入SQL注入check】 -->
<select id="queryDictTablePageList" parameterType="Object" resultType="org.jeecg.common.system.vo.DictModel">
select ${query.text} as "text",${query.code} as "value" from ${query.table}
where 1 = 1
select ${query.text} as "text", ${query.code} as "value" from ${query.table}
where
<if test="query.keyword != null and query.keyword != ''">
<bind name="bindKeyword" value="'%'+query.keyword+'%'"/>
and (${query.text} like #{bindKeyword} or ${query.code} like #{bindKeyword})
(${query.text} like #{bindKeyword} or ${query.code} like #{bindKeyword})
</if>
<if test="query.codeValue != null and query.codeValue != ''">
and ${query.code} = #{query.codeValue}
${query.code} = #{query.codeValue}
</if>
</select>
<!--通过查询指定table的 text code 获取字典数据,支持关键字和自定义查询条件查询 分页-->
<!--查询表字典数据,支持关键字和自定义查询条件【已加入SQL注入check】 -->
<sql id="queryTableDictWithFilterSqlFragment">
select ${text} as "text", ${code} as "value" from ${table}
<if test="filterSql != null and filterSql != ''">
where ${filterSql}
</if>
</sql>
<!--查询表字典数据,分页返回-->
<select id="queryPageTableDictWithFilter" parameterType="String" resultType="org.jeecg.common.system.vo.DictModel">
<include refid="queryTableDictWithFilterSqlFragment"></include>
</select>
<!--查询表字典数据,不分页返回-->
<select id="queryTableDictWithFilter" parameterType="String" resultType="org.jeecg.common.system.vo.DictModel">
select ${text} as "text", ${code} as "value" from ${table}
<if test="filterSql != null and filterSql != ''">
${filterSql}
</if>
<include refid="queryTableDictWithFilterSqlFragment"></include>
</select>
<!--通过查询指定table的 text code 获取字典数据,且支持关键字和自定义查询条件查询 获取所有 -->
<select id="queryAllTableDictItems" parameterType="String" resultType="org.jeecg.common.system.vo.DictModel">
select ${text} as "text", ${code} as "value" from ${table}
<if test="filterSql != null and filterSql != ''">
${filterSql}
</if>
</select>
<!-- 查询字典表的数据 支持设置过滤条件、设置存储值作为in查询条件 -->
<!-- 查询表字典数据, 支持设置过滤条件和code值 精确匹配查询【已加入SQL注入check】 -->
<select id="queryTableDictByKeysAndFilterSql" parameterType="String" resultType="org.jeecg.common.system.vo.DictModel">
select ${text} as "text", ${code} as "value" from ${table} where ${code} IN (
select ${text} as "text", ${code} as "value" from ${table}
where ${code} IN (
<foreach item="key" collection="codeValues" separator=",">
#{key}
</foreach>
@ -221,6 +182,8 @@
</if>
</select>
<!-- *****************以上方法写法存在SQL注入风险***************** -->
<!--根据应用id获取字典列表和详情-->
<select id="getDictListByLowAppId" resultType="org.jeecg.modules.system.entity.SysDict">
select id,dict_name,dict_code from sys_dict

View File

@ -1,11 +1,12 @@
package org.jeecg.modules.system.security;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.common.util.security.AbstractQueryBlackListHandler;
import org.springframework.stereotype.Component;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
@ -24,6 +25,17 @@ public class DictQueryBlackListHandler extends AbstractQueryBlackListHandler {
@Override
protected List<QueryTable> getQueryTableInfo(String dictCodeString) {
//针对转义字符进行解码
try {
if (dictCodeString.contains("%")) {
dictCodeString = URLDecoder.decode(dictCodeString, "UTF-8");
}
} catch (UnsupportedEncodingException e) {
//e.printStackTrace();
}
dictCodeString = dictCodeString.trim();
// 无论什么场景 第二、三个元素一定是表的字段直接add
if (dictCodeString != null && dictCodeString.indexOf(SymbolConstant.COMMA) > 0) {
String[] arr = dictCodeString.split(SymbolConstant.COMMA);
if (arr.length != 3 && arr.length != 4) {
@ -52,9 +64,18 @@ public class DictQueryBlackListHandler extends AbstractQueryBlackListHandler {
*/
private String getTableName(String str) {
String[] arr = str.split("\\s+(?i)where\\s+");
// sys_user , (sys_user), sys_user%20, %60sys_user%60 issues/4393
String tableName = arr[0].trim();
//【20230814】解决使用参数tableName=sys_user t&复测,漏洞仍然存在
if (tableName.contains(".")) {
tableName = tableName.substring(tableName.indexOf(".")+1, tableName.length()).trim();
}
if (tableName.contains(" ")) {
tableName = tableName.substring(0, tableName.indexOf(" ")).trim();
}
//【issues/4393】 sys_user , (sys_user), sys_user%20, %60sys_user%60
String reg = "\\s+|\\(|\\)|`";
return arr[0].replaceAll(reg, "");
return tableName.replaceAll(reg, "");
}
}

View File

@ -5,6 +5,7 @@ import org.jeecg.common.system.vo.DictModel;
import org.jeecg.common.system.vo.DictQuery;
import org.jeecg.modules.system.entity.SysDict;
import org.jeecg.modules.system.entity.SysDictItem;
import org.jeecg.modules.system.model.DuplicateCheckVo;
import org.jeecg.modules.system.model.TreeSelectModel;
import org.jeecg.modules.system.vo.lowapp.SysDictVo;
@ -21,6 +22,15 @@ import java.util.Map;
*/
public interface ISysDictService extends IService<SysDict> {
/**
* 校验数据是否可用,不存在重复数据
*
* @param duplicateCheckVo
* @return
*/
@Deprecated
public boolean duplicateCheckData(DuplicateCheckVo duplicateCheckVo);
/**
* 通过字典code获取字典数据
* @param code
@ -51,13 +61,13 @@ public interface ISysDictService extends IService<SysDict> {
/**
* 查通过查询指定table的 text code 获取字典
* @param table
* @param tableFilterSql
* @param text
* @param code
* @return
*/
@Deprecated
List<DictModel> queryTableDictItemsByCode(String table, String text, String code);
List<DictModel> queryTableDictItemsByCode(String tableFilterSql, String text, String code);
/**
* 通过查询指定table的 text code 获取字典(指定查询条件)
@ -206,7 +216,7 @@ public interface ISysDictService extends IService<SysDict> {
* @return
*/
@Deprecated
List<TreeSelectModel> queryTreeList(Map<String, String> query,String table, String text, String code, String pidField,String pid,String hasChildField,int converIsLeafVal);
List<TreeSelectModel> queryTreeList(Map<String, String> query, String table, String text, String code, String pidField, String pid, String hasChildField, int converIsLeafVal);
/**
* 真实删除
@ -235,7 +245,7 @@ public interface ISysDictService extends IService<SysDict> {
* @return
*/
@Deprecated
public List<DictModel> queryDictTablePageList(DictQuery query,int pageSize, int pageNo);
public List<DictModel> queryDictTablePageList(DictQuery query, int pageSize, int pageNo);
/**
* 获取字典数据

View File

@ -1,8 +1,8 @@
package org.jeecg.modules.system.service.impl;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.creator.DruidDataSourceCreator;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.creator.DataSourceProperty;
import com.baomidou.dynamic.datasource.creator.druid.DruidDataSourceCreator;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang.StringUtils;

View File

@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.config.TenantContext;
import org.jeecg.common.constant.CacheConstant;
import org.jeecg.common.constant.CommonConstant;
@ -13,11 +14,11 @@ import org.jeecg.common.constant.DataBaseConstant;
import org.jeecg.common.constant.SymbolConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.util.ResourceUtil;
import org.jeecg.common.system.vo.DictModel;
import org.jeecg.common.system.vo.DictModelMany;
import org.jeecg.common.system.vo.DictQuery;
import org.jeecg.common.util.CommonUtils;
import org.jeecg.common.util.SqlInjectionUtil;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
@ -25,14 +26,18 @@ import org.jeecg.modules.system.entity.SysDict;
import org.jeecg.modules.system.entity.SysDictItem;
import org.jeecg.modules.system.mapper.SysDictItemMapper;
import org.jeecg.modules.system.mapper.SysDictMapper;
import org.jeecg.modules.system.model.DuplicateCheckVo;
import org.jeecg.modules.system.model.TreeSelectModel;
import org.jeecg.modules.system.security.DictQueryBlackListHandler;
import org.jeecg.modules.system.service.ISysDictService;
import org.jeecg.modules.system.vo.lowapp.SysDictVo;
import org.mybatis.spring.MyBatisSystemException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.stream.Collectors;
@ -53,6 +58,53 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
private SysDictMapper sysDictMapper;
@Autowired
private SysDictItemMapper sysDictItemMapper;
@Autowired
private DictQueryBlackListHandler dictQueryBlackListHandler;
@Override
public boolean duplicateCheckData(DuplicateCheckVo duplicateCheckVo) {
Long count = null;
// 1.针对采用 ${}写法的表名和字段进行转义和check
String table = SqlInjectionUtil.getSqlInjectTableName(duplicateCheckVo.getTableName());
String fieldName = SqlInjectionUtil.getSqlInjectField(duplicateCheckVo.getFieldName());
duplicateCheckVo.setTableName(table);
duplicateCheckVo.setFieldName(fieldName);
// 2.SQL注入check只限制非法串改数据库
//关联表字典举例sys_user,realname,id
SqlInjectionUtil.filterContent(table, fieldName);
// 3.表字典黑名单check
String checkSql = table + SymbolConstant.COMMA + fieldName + SymbolConstant.COMMA;
dictQueryBlackListHandler.isPass(checkSql);
// 4.执行SQL 查询是否存在值
try{
if (StringUtils.isNotBlank(duplicateCheckVo.getDataId())) {
// [1].编辑页面校验
count = sysDictMapper.duplicateCheckCountSql(duplicateCheckVo);
} else {
// [2].添加页面校验
count = sysDictMapper.duplicateCheckCountSqlNoDataId(duplicateCheckVo);
}
}catch(MyBatisSystemException e){
log.error(e.getMessage(), e);
String errorCause = "查询异常,请检查唯一校验的配置!";
throw new JeecgBootException(errorCause);
}
// 4.返回结果
if (count == null || count == 0) {
// 该值可用
return true;
} else {
// 该值不可用
log.info("该值不可用,系统中已存在!");
return false;
}
}
/**
* 通过查询指定code 获取字典
@ -152,22 +204,69 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
/**
* 通过查询指定table的 text code 获取字典
* dictTableCache采用redis缓存有效期10分钟
* @param table
* @param tableFilterSql
* @param text
* @param code
* @return
*/
@Override
//@Cacheable(value = CacheConstant.SYS_DICT_TABLE_CACHE)
public List<DictModel> queryTableDictItemsByCode(String table, String text, String code) {
@Deprecated
public List<DictModel> queryTableDictItemsByCode(String tableFilterSql, String text, String code) {
log.debug("无缓存dictTableList的时候调用这里");
return sysDictMapper.queryTableDictItemsByCode(table,text,code);
// 1.表字典黑名单check
String str = tableFilterSql+","+text+","+code;
if(!dictQueryBlackListHandler.isPass(str)){
log.error(dictQueryBlackListHandler.getError());
return null;
}
// 2.分割SQL获取表名和条件
String table = null;
String filterSql = null;
if(tableFilterSql.toLowerCase().indexOf(DataBaseConstant.SQL_WHERE)>0){
String[] arr = tableFilterSql.split(" (?i)where ");
table = arr[0];
filterSql = oConvertUtils.getString(arr[1], null);
}else{
table = tableFilterSql;
}
// 3.SQL注入check
SqlInjectionUtil.filterContent(table, text, code);
SqlInjectionUtil.specialFilterContentForDictSql(filterSql);
// 4.针对采用 ${}写法的表名和字段进行转义和check
table = SqlInjectionUtil.getSqlInjectTableName(table);
text = SqlInjectionUtil.getSqlInjectField(text);
code = SqlInjectionUtil.getSqlInjectField(code);
//return sysDictMapper.queryTableDictItemsByCode(tableFilterSql,text,code);
return sysDictMapper.queryTableDictWithFilter(table,text,code,filterSql);
}
@Override
public List<DictModel> queryTableDictItemsByCodeAndFilter(String table, String text, String code, String filterSql) {
log.debug("无缓存dictTableList的时候调用这里");
return sysDictMapper.queryTableDictItemsByCodeAndFilter(table,text,code,filterSql);
// 1.SQL注入校验只限制非法串改数据库
SqlInjectionUtil.specialFilterContentForDictSql(table);
SqlInjectionUtil.filterContent(text, code);
SqlInjectionUtil.specialFilterContentForDictSql(filterSql);
// 2.表字典黑名单 Check
String str = table+","+text+","+code;
if(!dictQueryBlackListHandler.isPass(str)){
log.error(dictQueryBlackListHandler.getError());
return null;
}
// 3.针对采用 ${}写法的表名和字段进行转义和check
table = SqlInjectionUtil.getSqlInjectTableName(table);
text = SqlInjectionUtil.getSqlInjectField(text);
code = SqlInjectionUtil.getSqlInjectField(code);
return sysDictMapper.queryTableDictWithFilter(table,text,code,filterSql);
}
/**
@ -183,27 +282,70 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
@Cacheable(value = CacheConstant.SYS_DICT_TABLE_CACHE, unless = "#result == null ")
public String queryTableDictTextByKey(String table,String text,String code, String key) {
log.debug("无缓存dictTable的时候调用这里");
return sysDictMapper.queryTableDictTextByKey(table,text,code,key);
// 1.表字典黑名单check
String str = table+","+text+","+code;
if(!dictQueryBlackListHandler.isPass(str)){
log.error(dictQueryBlackListHandler.getError());
return null;
}
// 2.sql注入check
SqlInjectionUtil.filterContent(table, text, code, key);
// 3.针对采用 ${}写法的表名和字段进行转义和check
table = SqlInjectionUtil.getSqlInjectTableName(table);
text = SqlInjectionUtil.getSqlInjectField(text);
code = SqlInjectionUtil.getSqlInjectField(code);
List<DictModel> dictModeList = sysDictMapper.queryTableDictByKeysAndFilterSql(table, text, code, null, Arrays.asList(key));
if(CollectionUtils.isEmpty(dictModeList)){
return null;
}else{
return dictModeList.get(0).getText();
}
//此方法删除20230902
//return sysDictMapper.queryTableDictTextByKey(table,text,code,key);
}
@Override
public List<DictModel> queryTableDictTextByKeys(String table, String text, String code, List<String> keys) {
//update-begin-author:taoyan date:20220113 for: @dict注解支持 dicttable 设置where条件
public List<DictModel> queryTableDictTextByKeys(String table, String text, String code, List<String> codeValues) {
// 1.表字典黑名单check
String str = table+","+text+","+code;
if(!dictQueryBlackListHandler.isPass(str)){
log.error(dictQueryBlackListHandler.getError());
return null;
}
// 2.分割SQL获取表名和条件
String filterSql = null;
if(table.toLowerCase().indexOf(DataBaseConstant.SQL_WHERE)>0){
String[] arr = table.split(" (?i)where ");
table = arr[0];
filterSql = arr[1];
}
String[] tableAndFields = new String[]{table, text, code};
SqlInjectionUtil.filterContent(tableAndFields);
// 3.SQL注入check
SqlInjectionUtil.filterContent(table, text, code);
SqlInjectionUtil.specialFilterContentForDictSql(filterSql);
return sysDictMapper.queryTableDictByKeysAndFilterSql(table, text, code, filterSql, keys);
// 4.针对采用 ${}写法的表名和字段进行转义和check
table = SqlInjectionUtil.getSqlInjectTableName(table);
text = SqlInjectionUtil.getSqlInjectField(text);
code = SqlInjectionUtil.getSqlInjectField(code);
return sysDictMapper.queryTableDictByKeysAndFilterSql(table, text, code, filterSql, codeValues);
//update-end-author:taoyan date:20220113 for: @dict注解支持 dicttable 设置where条件
}
@Override
public List<String> queryTableDictByKeys(String table, String text, String code, String keys) {
String str = table+","+text+","+code;
if(!dictQueryBlackListHandler.isPass(str)){
log.error(dictQueryBlackListHandler.getError());
return null;
}
return this.queryTableDictByKeys(table, text, code, keys, true);
}
@ -213,46 +355,56 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
* @param table
* @param text
* @param code
* @param keys (逗号分隔)
* @param codeValuesStr (逗号分隔)
* @param delNotExist 是否移除不存在的项默认为true设为false如果某个key不存在数据库中则直接返回key本身
* @return
*/
@Override
//update-begin--Author:lvdandan Date:20201204 forJT-36【online】树形列表bug修改后还是显示原来值 暂时去掉缓存
//@Cacheable(value = CacheConstant.SYS_DICT_TABLE_BY_KEYS_CACHE)
//update-end--Author:lvdandan Date:20201204 forJT-36【online】树形列表bug修改后还是显示原来值 暂时去掉缓存
public List<String> queryTableDictByKeys(String table, String text, String code, String keys, boolean delNotExist) {
if(oConvertUtils.isEmpty(keys)){
public List<String> queryTableDictByKeys(String table, String text, String code, String codeValuesStr, boolean delNotExist) {
if(oConvertUtils.isEmpty(codeValuesStr)){
return null;
}
String[] keyArray = keys.split(",");
//update-begin-author:taoyan date:2022-4-24 for: 下拉搜索组件表单编辑页面回显下拉搜索的文本的时候因为表名后配置了条件导致sql执行失败
//1.分割sql获取表名 和 条件sql
String filterSql = null;
if(table.toLowerCase().indexOf("where")!=-1){
String[] arr = table.split(" (?i)where ");
table = arr[0];
filterSql = arr[1];
}
String[] tableAndFields = new String[]{table, text, code};
SqlInjectionUtil.filterContent(tableAndFields);
SqlInjectionUtil.specialFilterContentForDictSql(filterSql);
List<DictModel> dicts = sysDictMapper.queryTableDictByKeysAndFilterSql(table, text, code, filterSql, Arrays.asList(keyArray));
//update-end-author:taoyan date:2022-4-24 for: 下拉搜索组件表单编辑页面回显下拉搜索的文本的时候因为表名后配置了条件导致sql执行失败
List<String> texts = new ArrayList<>(dicts.size());
// update-begin--author:sunjianlei--date:20210514--for新增delNotExist参数设为false不删除数据库里不存在的key ----
// 查询出来的顺序可能是乱的,需要排个序
for (String key : keyArray) {
List<DictModel> res = dicts.stream().filter(i -> key.equals(i.getValue())).collect(Collectors.toList());
// 2.SQL注入check
SqlInjectionUtil.filterContent(table, text, code);
SqlInjectionUtil.specialFilterContentForDictSql(filterSql);
// 3.表字典黑名单check
String str = table+","+text+","+code;
if(!dictQueryBlackListHandler.isPass(str)){
log.error(dictQueryBlackListHandler.getError());
return null;
}
// 4.针对采用 ${}写法的表名和字段进行转义和check
table = SqlInjectionUtil.getSqlInjectTableName(table);
text = SqlInjectionUtil.getSqlInjectField(text);
code = SqlInjectionUtil.getSqlInjectField(code);
//字典条件值
String[] codeValues = codeValuesStr.split(",");
// 5.查询字典数据
List<DictModel> dicts = sysDictMapper.queryTableDictByKeysAndFilterSql(SqlInjectionUtil.getSqlInjectTableName(table),
SqlInjectionUtil.getSqlInjectField(text), SqlInjectionUtil.getSqlInjectField(code), filterSql, Arrays.asList(codeValues));
List<String> texts = new ArrayList<>(dicts.size());
// 6.查询出来的顺序可能是乱的,需要排个序
for (String conditionalVal : codeValues) {
List<DictModel> res = dicts.stream().filter(i -> conditionalVal.equals(i.getValue())).collect(Collectors.toList());
if (res.size() > 0) {
texts.add(res.get(0).getText());
} else if (!delNotExist) {
texts.add(key);
texts.add(conditionalVal);
}
}
// update-end--author:sunjianlei--date:20210514--for新增delNotExist参数设为false不删除数据库里不存在的key ----
return texts;
}
@ -305,35 +457,44 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
// }
@Override
public List<DictModel> queryLittleTableDictItems(String table, String text, String code, String condition, String keyword, int pageSize) {
public List<DictModel> queryLittleTableDictItems(String tableSql, String text, String code, String condition, String keyword, int pageSize) {
Page<DictModel> page = new Page<DictModel>(1, pageSize);
page.setSearchCount(false);
//为了防止sqljeecg提供了防注入的方法可以在拼接 SQL 语句时自动对参数进行转义避免SQL注入攻击
// 1. 针对采用 ${}写法的表名和字段进行转义和check
String table = SqlInjectionUtil.getSqlInjectTableName(CommonUtils.getTableNameByTableSql(tableSql));
text = SqlInjectionUtil.getSqlInjectField(text);
code = SqlInjectionUtil.getSqlInjectField(code);
//【issues/3713】字典接口存在SQL注入风险
SqlInjectionUtil.specialFilterContentForDictSql(code);
String filterSql = getFilterSql(table, text, code, condition, keyword);
IPage<DictModel> pageList = baseMapper.queryTableDictWithFilter(page, table, text, code, filterSql);
// 2. 查询条件SQL (获取条件sql方法含sql注入校验)
String filterSql = getFilterSql(tableSql, text, code, condition, keyword);
// 3. 返回表字典数据
IPage<DictModel> pageList = baseMapper.queryPageTableDictWithFilter(page, table, text, code, filterSql);
return pageList.getRecords();
}
/**
* 获取条件语句
* 获取条件语句 (下拉搜索组件 支持传入排序信息 查询排序)
*
* @param text
* @param code
* @param condition
* @param keyword
* @return
*/
private String getFilterSql(String table, String text, String code, String condition, String keyword){
String keywordSql = null, filterSql = "", sqlWhere = " where ";
// update-begin-author:sunjianlei date:20220112 for: 【JTC-631】判断如果 table 携带了 where 条件,那么就使用 and 查询,防止报错
if (table.toLowerCase().contains(sqlWhere)) {
sqlWhere = " and ";
private String getFilterSql(String tableSql, String text, String code, String condition, String keyword){
String filterSql = "";
String keywordSql = null;
String sqlWhere = "where ";
//【JTC-631】判断如果 table 携带了 where 条件,那么就使用 and 查询,防止报错
if (tableSql.toLowerCase().contains(sqlWhere)) {
sqlWhere = CommonUtils.getFilterSqlByTableSql(tableSql) + " and ";
}
// update-end-author:sunjianlei date:20220112 for: 【JTC-631】判断如果 table 携带了 where 条件,那么就使用 and 查询,防止报错
//update-begin-author:taoyan date:2022-8-15 for: 下拉搜索组件 支持传入排序信息 查询排序
// 下拉搜索组件 支持传入排序信息 查询排序
String orderField = "", orderType = "";
if (oConvertUtils.isNotEmpty(keyword)) {
// 关键字里面如果写入了 排序信息 xxxxx[orderby:create_time,desc]
@ -358,7 +519,8 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
}
}
}
//update-end-author:taoyan date:2022-8-15 for: 下拉搜索组件 支持传入排序信息 查询排序
//下拉搜索组件 支持传入排序信息 查询排序
if(oConvertUtils.isNotEmpty(condition) && oConvertUtils.isNotEmpty(keywordSql)){
filterSql+= sqlWhere + condition + " and " + keywordSql;
}else if(oConvertUtils.isNotEmpty(condition)){
@ -366,24 +528,71 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
}else if(oConvertUtils.isNotEmpty(keywordSql)){
filterSql+= sqlWhere + keywordSql;
}
//update-begin-author:taoyan date:2022-8-15 for: 下拉搜索组件 支持传入排序信息 查询排序
// 增加排序逻辑
if (oConvertUtils.isNotEmpty(orderField)) {
filterSql += " order by " + orderField + " " + orderType;
}
//update-end-author:taoyan date:2022-8-15 for: 下拉搜索组件 支持传入排序信息 查询排序
return filterSql;
// 处理返回条件
// 1.1 返回条件SQL去掉开头的 where
final String wherePrefix = "(?i)where "; // (?i) 表示不区分大小写
String filterSqlString = filterSql.trim().replaceAll(wherePrefix, "");
// 1.2 条件SQL进行漏洞 check
SqlInjectionUtil.specialFilterContentForDictSql(filterSqlString);
// 1.3 判断如何返回条件是 order by开头则前面拼上 1=1
if (oConvertUtils.isNotEmpty(filterSqlString) && filterSqlString.trim().toUpperCase().startsWith("ORDER")) {
filterSqlString = " 1=1 " + filterSqlString;
}
return filterSqlString;
}
@Override
public List<DictModel> queryAllTableDictItems(String table, String text, String code, String condition, String keyword) {
// 1.获取条件sql
String filterSql = getFilterSql(table, text, code, condition, keyword);
List<DictModel> ls = baseMapper.queryAllTableDictItems(table, text, code, filterSql);
// 为了防止sqljeecg提供了防注入的方法可以在拼接 SQL 语句时自动对参数进行转义避免SQL注入攻击
// 2.针对采用 ${}写法的表名和字段进行转义和check
table = SqlInjectionUtil.getSqlInjectTableName(table);
text = SqlInjectionUtil.getSqlInjectField(text);
code = SqlInjectionUtil.getSqlInjectField(code);
List<DictModel> ls = baseMapper.queryTableDictWithFilter(table, text, code, filterSql);
return ls;
}
@Override
public List<TreeSelectModel> queryTreeList(Map<String, String> query,String table, String text, String code, String pidField,String pid,String hasChildField,int converIsLeafVal) {
return baseMapper.queryTreeList(query, table, text, code, pidField, pid, hasChildField,converIsLeafVal);
public List<TreeSelectModel> queryTreeList(Map<String, String> query, String table, String text, String code, String pidField, String pid, String hasChildField, int converIsLeafVal) {
//为了防止sqljeecg提供了防注入的方法可以在拼接 SQL 语句时自动对参数进行转义避免SQL注入攻击
// 1.针对采用 ${}写法的表名和字段进行转义和check
table = SqlInjectionUtil.getSqlInjectTableName(table);
text = SqlInjectionUtil.getSqlInjectField(text);
code = SqlInjectionUtil.getSqlInjectField(code);
pidField = SqlInjectionUtil.getSqlInjectField(pidField);
hasChildField = SqlInjectionUtil.getSqlInjectField(hasChildField);
// 2.检测最终SQL是否存在SQL注入风险
String dictCode = table + "," + text + "," + code;
SqlInjectionUtil.filterContent(dictCode);
// 3.表字典SQL表名黑名单 Check
if(!dictQueryBlackListHandler.isPass(dictCode)){
log.error("Sql异常{}", dictQueryBlackListHandler.getError());
return null;
}
// 4.检测查询条件是否存在SQL注入
Map<String, String> queryParams = null;
if (query != null) {
queryParams = new HashMap<>(5);
for (Map.Entry<String, String> searchItem : query.entrySet()) {
String fieldName = searchItem.getKey();
queryParams.put(SqlInjectionUtil.getSqlInjectField(fieldName), searchItem.getValue());
}
}
return baseMapper.queryTreeList(queryParams, table, text, code, pidField, pid, hasChildField, converIsLeafVal);
}
@Override
@ -405,6 +614,26 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
@Override
public List<DictModel> queryDictTablePageList(DictQuery query, int pageSize, int pageNo) {
Page page = new Page(pageNo,pageSize,false);
//为了防止sqljeecg提供了防注入的方法可以在拼接 SQL 语句时自动对参数进行转义避免SQL注入攻击
// 1. 针对采用 ${}写法的表名和字段进行转义和check
String table = SqlInjectionUtil.getSqlInjectTableName(query.getTable());
String text = SqlInjectionUtil.getSqlInjectTableName(query.getText());
String code = SqlInjectionUtil.getSqlInjectTableName(query.getCode());
query.setCode(table);
query.setTable(text);
query.setText(code);
// 2.表字典黑名单check
String dictCode = table+","+text+","+code;
if(!dictQueryBlackListHandler.isPass(dictCode)){
log.error(dictQueryBlackListHandler.getError());
return null;
}
// 3.SQL注入check
SqlInjectionUtil.filterContent(dictCode);
Page<DictModel> pageList = baseMapper.queryDictTablePageList(page, query);
return pageList.getRecords();
}
@ -419,17 +648,8 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
// 字典Code格式不正确
return null;
}
//SQL注入校验只限制非法串改数据库
//update-begin-author:taoyan date:2022-7-4 for: issues/I5BNY9 指定带过滤条件的字典table在生成代码后失效
// 表名后也有可能带条件and语句 不能走filterContent方法
SqlInjectionUtil.specialFilterContentForDictSql(params[0]);
final String[] sqlInjCheck = {params[1], params[2]};
//update-end-author:taoyan date:2022-7-4 for: issues/I5BNY9 指定带过滤条件的字典table在生成代码后失效
//【issues/3713】字典接口存在SQL注入风险
SqlInjectionUtil.filterContent(sqlInjCheck);
if (params.length == 4) {
// SQL注入校验查询条件SQL 特殊check此方法仅供此处使用
SqlInjectionUtil.specialFilterContentForDictSql(params[3]);
ls = this.queryTableDictItemsByCodeAndFilter(params[0], params[1], params[2], params[3]);
} else if (params.length == 3) {
ls = this.queryTableDictItemsByCode(params[0], params[1], params[2]);
@ -454,7 +674,13 @@ public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> impl
@Override
public List<DictModel> loadDict(String dictCode, String keyword, Integer pageSize) {
//【issues/3713】字典接口存在SQL注入风险
// 1.表字典黑名单check
if(!dictQueryBlackListHandler.isPass(dictCode)){
log.error(dictQueryBlackListHandler.getError());
return null;
}
// 2.字典SQL注入风险check
SqlInjectionUtil.specialFilterContentForDictSql(dictCode);
if (dictCode.contains(SymbolConstant.COMMA)) {

View File

@ -6,6 +6,8 @@ import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Base64;
import java.util.Random;
@ -96,7 +98,13 @@ public class RandImageUtil {
// graphics.setColor(getRandColor(100, 200)); // ---2
graphics.drawRect(0, 0, WIDTH - 1, HEIGHT - 1);
final Random random = new Random();
// SHA1PRNG是-种常用的随机数生成算法,处理弱随机数问题
SecureRandom random;
try {
random = SecureRandom.getInstance("SHA1PRNG");
} catch (NoSuchAlgorithmException e) {
random = new SecureRandom();
}
// 随机产生干扰线,使图象中的认证码不易被其它程序探测到
for (int i = 0; i < COUNT; i++) {
// ---3

View File

@ -11,6 +11,6 @@ WORKDIR /jeecg-boot
EXPOSE 8080
#ADD ./src/main/resources/jeecg ./config/jeecg
ADD ./target/jeecg-system-start-3.5.3.jar ./
ADD ./target/jeecg-system-start-3.5.5.jar ./
CMD sleep 60;java -Djava.security.egd=file:/dev/./urandom -jar jeecg-system-start-3.5.3.jar
CMD sleep 60;java -Djava.security.egd=file:/dev/./urandom -jar jeecg-system-start-3.5.5.jar

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-module-system</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.5.3</version>
<version>3.5.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -127,8 +127,10 @@ spring:
maxPoolPreparedStatementPerConnectionSize: 20
# 配置监控统计拦截的filters去掉后监控界面sql无法统计'wall'用于防火墙
filters: stat,wall,slf4j
# 通过connectProperties属性来打开mergeSql功能慢SQL记录
connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
# 打开mergeSql功能慢SQL记录
stat:
merge-sql: true
slow-sql-millis: 5000
datasource:
master:
url: jdbc:mysql://127.0.0.1:3306/jeecg-boot?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
@ -207,9 +209,14 @@ jeecg:
bucketName: otatest
#大屏报表参数设置
jmreport:
mode: dev
#数据字典是否进行saas数据隔离自己看自己的字典
saas: false
#多租户模式,默认值为空(created:按照创建人隔离、tenant:按照租户隔离) (v1.6.2+ 新增)
saasMode:
# 平台上线安全配置(v1.6.2+ 新增)
firewall:
# 数据源安全 (开启后不允许使用平台数据源、SQL解析加签并且不允许查询数据库)
dataSourceSafe: false
# 低代码开发模式dev:开发模式prod:发布模式—关闭在线报表设计功能分配角色admin、lowdeveloper可以放开限制
lowCodeMode: dev
#xxl-job配置
xxljob:
enabled: false

View File

@ -127,8 +127,10 @@ spring:
maxPoolPreparedStatementPerConnectionSize: 20
# 配置监控统计拦截的filters去掉后监控界面sql无法统计'wall'用于防火墙
filters: stat,wall,slf4j
# 通过connectProperties属性来打开mergeSql功能慢SQL记录
connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
# 打开mergeSql功能慢SQL记录
stat:
merge-sql: true
slow-sql-millis: 5000
datasource:
master:
url: jdbc:mysql://127.0.0.1:3306/jeecg-boot?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
@ -208,17 +210,14 @@ jeecg:
bucketName: otatest
#大屏报表参数设置
jmreport:
mode: prod
#数据字典是否进行saas数据隔离自己看自己的字典
saas: false
#是否开启租户模式 Support By v1.5.5+
openTenant: false
#安全模式(敏感接口校验、saas模式下不允许使用平台数据源)
#safeMode: true
#是否需要校验token
is_verify_token: true
#必须校验方法
verify_methods: remove,delete,save,add,update
#多租户模式,默认值为空(created:按照创建人隔离、tenant:按照租户隔离) (v1.6.2+ 新增)
saasMode: created
# 平台上线安全配置(v1.6.2+ 新增)
firewall:
# 数据源安全 (开启后不允许使用平台数据源、SQL解析加签并且不允许查询数据库)
dataSourceSafe: true
# 低代码开发模式dev:开发模式prod:发布模式—关闭在线报表设计功能分配角色admin、lowdeveloper可以放开限制
lowCodeMode: prod
#xxl-job配置
xxljob:
enabled: false

View File

@ -127,8 +127,10 @@ spring:
maxPoolPreparedStatementPerConnectionSize: 20
# 配置监控统计拦截的filters去掉后监控界面sql无法统计'wall'用于防火墙
filters: stat,wall,slf4j
# 通过connectProperties属性来打开mergeSql功能慢SQL记录
connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
# 打开mergeSql功能慢SQL记录
stat:
merge-sql: true
slow-sql-millis: 5000
datasource:
master:
url: jdbc:mysql://127.0.0.1:3306/jeecg-boot?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai
@ -208,17 +210,14 @@ jeecg:
bucketName: ??
#大屏报表参数设置
jmreport:
mode: prod
#数据字典是否进行saas数据隔离自己看自己的字典
saas: false
#是否开启租户模式 Support By v1.5.5+
openTenant: false
#安全模式(敏感接口校验、saas模式下不允许使用平台数据源)
#safeMode: true
#是否需要校验token
is_verify_token: false
#必须校验方法
verify_methods: remove,delete,save,add,update
#多租户模式,默认值为空(created:按照创建人隔离、tenant:按照租户隔离) (v1.6.2+ 新增)
saasMode: created
# 平台上线安全配置(v1.6.2+ 新增)
firewall:
# 数据源安全 (开启后不允许使用平台数据源、SQL解析加签并且不允许查询数据库)
dataSourceSafe: true
# 低代码开发模式dev:开发模式prod:发布模式—关闭在线报表设计功能分配角色admin、lowdeveloper可以放开限制
lowCodeMode: prod
#xxl-job配置
xxljob:
enabled: false

View File

@ -9,6 +9,6 @@ ${AnsiColor.BRIGHT_BLUE}
${AnsiColor.BRIGHT_GREEN}
Jeecg Boot Version: 3.5.3
Jeecg Boot Version: 3.5.5
Spring Boot Version: ${spring-boot.version}${spring-boot.formatted-version}
${AnsiColor.BLACK}

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-boot-parent</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.5.3</version>
<version>3.5.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -10,6 +10,6 @@ WORKDIR /jeecg-cloud-gateway
EXPOSE 9999
ADD ./target/jeecg-cloud-gateway-3.5.3.jar ./
ADD ./target/jeecg-cloud-gateway-3.5.5.jar ./
CMD sleep 1;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-cloud-gateway-3.5.3.jar
CMD sleep 1;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-cloud-gateway-3.5.5.jar

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-server-cloud</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.5.3</version>
<version>3.5.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-cloud-gateway</artifactId>

View File

@ -21,6 +21,7 @@ import org.jeecg.config.RouterDataType;
import org.jeecg.loader.repository.DynamicRouteService;
import org.jeecg.loader.repository.MyInMemoryRouteDefinitionRepository;
import org.jeecg.loader.vo.MyRouteDefinition;
import org.jeecg.loader.vo.PredicatesVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
@ -35,10 +36,7 @@ import reactor.core.publisher.Mono;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.*;
import java.util.concurrent.Executor;
/**
@ -207,10 +205,26 @@ public class DynamicRouteLoader implements ApplicationEventPublisherAware {
}
Object predicates = obj.get("predicates");
if (predicates != null) {
JSONArray list = JSON.parseArray(predicates.toString());
List<PredicatesVo> list = JSON.parseArray(predicates.toString(), PredicatesVo.class);
Map<String, List<String>> groupedPredicates = new HashMap<>();
for (PredicatesVo predicatesVo : list) {
String name = predicatesVo.getName();
List<String> args = predicatesVo.getArgs();
groupedPredicates.computeIfAbsent(name, k -> new ArrayList<>()).addAll(args);
}
list = new ArrayList<>();
for (Map.Entry<String, List<String>> entry : groupedPredicates.entrySet()) {
String name = entry.getKey();
List<String> args = entry.getValue();
list.add(new PredicatesVo(name, args));
}
List<PredicateDefinition> predicateDefinitionList = new ArrayList<>();
for (Object map : list) {
JSONObject json = (JSONObject) map;
JSONObject json = JSON.parseObject(JSON.toJSONString(map));
PredicateDefinition predicateDefinition = new PredicateDefinition();
//update-begin-author:zyf date:20220419 for:【VUEN-762】路由条件添加异常问题,原因是部分路由条件参数需要设置固定key
String name=json.getString("name");

View File

@ -0,0 +1,16 @@
package org.jeecg.loader.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PredicatesVo {
private String name;
private List<String> args;
}

View File

@ -1,4 +1,4 @@
FROM anapsix/alpine-java:8_server-jre_unlimited
FROM alibabadragonwell/dragonwell:17-anolis
MAINTAINER jeecgos@163.com
@ -10,6 +10,6 @@ WORKDIR /jeecg-cloud-nacos
EXPOSE 8848
ADD ./target/jeecg-cloud-nacos-3.5.3.jar ./
ADD ./target/jeecg-cloud-nacos-3.5.5.jar ./
CMD sleep 1;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-cloud-nacos-3.5.3.jar
CMD sleep 1;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-cloud-nacos-3.5.5.jar

View File

@ -5,7 +5,7 @@
<artifactId>jeecg-cloud-nacos</artifactId>
<name>jeecg-cloud-nacos</name>
<description>nacos启动模块</description>
<version>3.5.3</version>
<version>3.5.5</version>
<parent>
<groupId>org.springframework.boot</groupId>

View File

@ -10,6 +10,6 @@ WORKDIR /jeecg-demo-cloud
EXPOSE 7002
ADD ./target/jeecg-demo-cloud-start-3.5.3.jar ./
ADD ./target/jeecg-demo-cloud-start-3.5.5.jar ./
CMD sleep 1;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-demo-cloud-start-3.5.3.jar
CMD sleep 1;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-demo-cloud-start-3.5.5.jar

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-server-cloud</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.5.3</version>
<version>3.5.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -10,6 +10,6 @@ WORKDIR /jeecg-system-cloud
EXPOSE 7001
ADD ./target/jeecg-system-cloud-start-3.5.3.jar ./
ADD ./target/jeecg-system-cloud-start-3.5.5.jar ./
CMD sleep 1;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-system-cloud-start-3.5.3.jar
CMD sleep 1;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-system-cloud-start-3.5.5.jar

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-server-cloud</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.5.3</version>
<version>3.5.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-system-cloud-start</artifactId>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-visual</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.5.3</version>
<version>3.5.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-cloud-monitor</artifactId>

View File

@ -10,6 +10,6 @@ WORKDIR /jeecg-cloud-sentinel
EXPOSE 8848
ADD ./target/jeecg-cloud-sentinel-3.5.3.jar ./
ADD ./target/jeecg-cloud-sentinel-3.5.5.jar ./
CMD sleep 5;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-cloud-sentinel-3.5.3.jar
CMD sleep 5;java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-cloud-sentinel-3.5.5.jar

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-visual</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.5.3</version>
<version>3.5.5</version>
</parent>
<artifactId>jeecg-cloud-sentinel</artifactId>
<name>jeecg-cloud-sentinel</name>
@ -116,7 +116,7 @@
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
<version>4.5.14</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-cloud-test</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.5.3</version>
<version>3.5.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<description>公共测试模块</description>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-cloud-test</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.5.3</version>
<version>3.5.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<description>消息队列测试模块</description>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-cloud-test-seata</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.5.3</version>
<version>3.5.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<description>分布式事务测试模块</description>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-cloud-test-seata</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.5.3</version>
<version>3.5.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<description>分布式事务测试模块</description>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-cloud-test-seata</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.5.3</version>
<version>3.5.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<description>分布式事务测试模块</description>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-cloud-test</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.5.3</version>
<version>3.5.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jeecg-cloud-test-seata</artifactId>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-cloud-test</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.5.3</version>
<version>3.5.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-visual</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.5.3</version>
<version>3.5.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -10,7 +10,7 @@ WORKDIR /jeecg-cloud-xxljob
EXPOSE 9080
ADD ./target/jeecg-cloud-xxljob-3.5.3.jar ./
ADD ./target/jeecg-cloud-xxljob-3.5.5.jar ./
CMD java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-cloud-xxljob-3.5.3.jar
CMD java -Dfile.encoding=utf-8 -Djava.security.egd=file:/dev/./urandom -jar jeecg-cloud-xxljob-3.5.5.jar

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-visual</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.5.3</version>
<version>3.5.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -2,7 +2,7 @@
<configuration debug="false" scan="true" scanPeriod="1 seconds">
<contextName>logback</contextName>
<property name="log.path" value="/data/applogs/xxl-job/xxl-job-admin.log"/>
<property name="log.path" value="../xxl-job/xxl-job-admin.log"/>
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-server-cloud</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.5.3</version>
<version>3.5.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<artifactId>jeecg-boot-parent</artifactId>
<groupId>org.jeecgframework.boot</groupId>
<version>3.5.3</version>
<version>3.5.5</version>
</parent>
<modelVersion>4.0.0</modelVersion>

26
pom.xml
View File

@ -2,13 +2,13 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>jeecg-boot-parent</artifactId>
<version>3.5.3</version>
<version>3.5.5</version>
<packaging>pom</packaging>
<name>JEECG BOOT ${project.version} </name>
<developers>
<developer>
<name>北京敲敲云科技有限公司</name>
<name>北京国炬信息技术有限公司</name>
<email>jeecgos@163.com</email>
</developer>
</developers>
@ -27,7 +27,7 @@
</parent>
<properties>
<jeecgboot.version>3.5.3</jeecgboot.version>
<jeecgboot.version>3.5.5</jeecgboot.version>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@ -49,21 +49,21 @@
<hutool.version>5.3.8</hutool.version>
<!-- 持久层 -->
<mybatis-plus.version>3.5.1</mybatis-plus.version>
<dynamic-datasource-spring-boot-starter.version>3.2.0</dynamic-datasource-spring-boot-starter.version>
<druid.version>1.1.22</druid.version>
<minidao.version>1.9.1</minidao.version>
<mybatis-plus.version>3.5.3.1</mybatis-plus.version>
<dynamic-datasource-spring-boot-starter.version>4.1.3</dynamic-datasource-spring-boot-starter.version>
<druid.version>1.2.19</druid.version>
<minidao.version>1.9.5</minidao.version>
<!-- 积木报表-->
<jimureport-spring-boot-starter.version>1.5.9</jimureport-spring-boot-starter.version>
<jimureport-spring-boot-starter.version>1.6.4</jimureport-spring-boot-starter.version>
<commons.version>2.6</commons.version>
<aliyun-java-sdk-dysmsapi.version>2.1.0</aliyun-java-sdk-dysmsapi.version>
<aliyun.oss.version>3.11.2</aliyun.oss.version>
<!-- shiro -->
<shiro.version>1.10.0</shiro.version>
<shiro.version>1.12.0</shiro.version>
<java-jwt.version>3.11.0</java-jwt.version>
<shiro-redis.version>3.1.0</shiro-redis.version>
<codegenerate.version>1.4.3</codegenerate.version>
<codegenerate.version>1.4.4</codegenerate.version>
<autopoi-web.version>1.4.5</autopoi-web.version>
<minio.version>8.0.3</minio.version>
<justauth-spring-boot-starter.version>1.3.4</justauth-spring-boot-starter.version>
@ -235,7 +235,7 @@
<dependency>
<groupId>org.jeecgframework.boot</groupId>
<artifactId>hibernate-re</artifactId>
<version>3.5.3-beta</version>
<version>3.5.3</version>
</dependency>
<!--mongon db-->
@ -267,7 +267,7 @@
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
<version>1.5</version>
<exclusions>
<exclusion>
<artifactId>commons-io</artifactId>
@ -317,7 +317,7 @@
<dependency>
<groupId>org.jeecgframework</groupId>
<artifactId>jeewx-api</artifactId>
<version>1.5.1</version>
<version>1.5.2</version>
<exclusions>
<exclusion>
<artifactId>commons-beanutils</artifactId>