453 Commits
v2.1 ... v3.3.0

Author SHA1 Message Date
RuoYi
3c7018b38a 若依 3.3.0 2021-12-13 09:02:33 +08:00
RuoYi
2a5091c6f4 优化下载解析blob异常提示 2021-12-10 10:02:22 +08:00
RuoYi
b6222b9755 升级dynamic-ds到最新版本3.5.0 2021-12-10 09:51:22 +08:00
RuoYi
4db3e90872 代码生成预览支持复制内容 2021-12-09 10:03:43 +08:00
RuoYi
19ac02fd70 自定义文字复制剪贴指令 2021-12-09 10:03:07 +08:00
RuoYi
9d094587b3 升级clipboard到最新版本2.0.8 2021-12-09 10:02:42 +08:00
RuoYi
2bc2b08bc7 升级spring-boot-admin到最新版2.5.4 2021-12-07 13:48:52 +08:00
RuoYi
f64a5dd5ca 修正用户分配角色属性错误 2021-12-06 21:56:00 +08:00
RuoYi
9f21dbbc5c 修复长主键溢出问题 将查询返回类型改为 Long 2021-12-06 21:55:41 +08:00
RuoYi
05ce7d92a9 🎉 RuoYi-Cloud-Vue3(Vue3 Element Plus Vite)版本 2021-12-02 10:47:30 +08:00
RuoYi
2e17d9c084 Crontab组件优化 2021-12-02 10:44:46 +08:00
RuoYi
82779f3c70 优化提示信息 2021-12-02 10:44:15 +08:00
RuoYi
b1bc3ceb27 注册成功提示类型success 2021-11-26 18:10:34 +08:00
RuoYi
e2a7df4a2c camelCase中应该是下划线,而不是横杠 2021-11-26 18:09:50 +08:00
Ricky
2a452a00e0 升级velocity到最新版本2.3(语法升级) 2021-11-25 15:23:46 +08:00
Ricky
4d4123243c 修复代码生成复选框字典遗漏问题 2021-11-25 13:42:06 +08:00
RuoYi
2c1bdc9670 添加新群号:236543183 2021-11-25 10:06:29 +08:00
RuoYi
08885f65cd 升级velocity到最新版本2.3 2021-11-24 16:40:18 +08:00
RuoYi
961825d25c update bin 2021-11-24 16:39:55 +08:00
RuoYi
337d1bab02 优化前端代码 2021-11-24 16:37:20 +08:00
Ricky
b6a71fe988 防止修改用户个人信息接口修改用户名 2021-11-22 22:54:24 +08:00
RuoYi
786df8e278 升级js-cookie到最新版本3.0.1 2021-11-22 18:13:49 +08:00
RuoYi
451d218f4b 优化提示信息 2021-11-22 18:13:39 +08:00
RuoYi
adcb6194c8 新增tab对象简化页签操作 2021-11-19 17:58:55 +08:00
RuoYi
334f79efe4 升级jsencrypt到最新版本3.2.1 2021-11-18 17:54:57 +08:00
RuoYi
73b38b143b 代码生成模板主子表删除方法缺少事务 2021-11-18 17:54:20 +08:00
RuoYi
ef541b220b 删除多余的通用配置 2021-11-18 17:53:31 +08:00
RuoYi
173c0e384f 优化导出数据操作 2021-11-17 12:12:58 +08:00
RuoYi
360ccc7adc 修复响应体过大出现的乱码问题 2021-11-16 18:50:17 +08:00
RuoYi
df760d3504 任务参数忽略双引号中的逗号 2021-11-16 18:49:36 +08:00
RuoYi
0beecf7ea1 升级core-js到最新版本3.19.1 2021-11-16 18:49:26 +08:00
若依
aa2821a19d !118 update ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/aspect/LogAspect.java.
Merge pull request !118 from TwelveT/N/A
2021-11-16 10:43:54 +00:00
TwelveT
2288fa218e update ruoyi-common/ruoyi-common-log/src/main/java/com/ruoyi/common/log/aspect/LogAspect.java.
修复feign对过大的参数会直接报错,无法调用BUG
2021-11-12 09:01:56 +00:00
RuoYi
6adc583c38 升级spring-boot-admin到最新版2.5.3 2021-11-10 11:29:39 +08:00
RuoYi
52111e4bf9 升级axios到最新版本0.24.0 2021-11-10 11:27:54 +08:00
RuoYi
68db4092ed 任务屏蔽违规字符 2021-11-01 15:45:22 +08:00
RuoYi
acf8d9719f 修复字符串无法被反转义问题 2021-11-01 15:45:10 +08:00
RuoYi
92e5d2a97a 回显数据字典键值修正 2021-11-01 15:44:58 +08:00
RuoYi
e165901506 登录/验证码请求headers不设置token 2021-11-01 15:44:42 +08:00
RuoYi
3187b1c46e 升级spring-boot到最新版本2.5.6 2021-10-27 16:56:54 +08:00
RuoYi
662dec2fe2 修正错别字 2021-10-25 10:29:27 +08:00
RuoYi
3901695a6f 解析blob响应是否登录失效 2021-10-25 09:49:13 +08:00
RuoYi
d0a5c25b5d 新增认证对象简化权限验证 2021-10-20 11:23:18 +08:00
RuoYi
9c5c6c6be7 优化获取缓存信息方式 2021-10-18 10:59:56 +08:00
RuoYi
d8da1b796c 优化权限认证注解 2021-10-16 18:28:38 +08:00
RuoYi
e2dfdb2236 生产环境使用路由懒加载提升页面响应速度 2021-10-15 17:56:28 +08:00
RuoYi
a8eba6949e 角色列表返回类型保持一致 2021-10-15 17:30:30 +08:00
RuoYi
3e907e8da7 修复五级以上菜单404问题 2021-10-14 16:24:39 +08:00
RuoYi
af1b557bc8 若依 3.2.0 2021-10-12 09:01:05 +08:00
RuoYi
e6c3bd1ce5 升级spring-boot-admin到最新版2.5.2 2021-10-11 18:57:21 +08:00
RuoYi
046d25f35d 升级spring-boot到最新版本2.5.5 2021-10-10 16:07:43 +08:00
RuoYi
d20d4ffa16 菜单子项添加路由参数 2021-10-10 16:07:06 +08:00
RuoYi
76f2273d0b Excel导入支持@Excels注解 2021-10-10 16:02:54 +08:00
RuoYi
dda78c95b7 升级pagehelper到最新版1.4.0 2021-10-10 16:01:07 +08:00
RuoYi
ebbeb047be 升级druid到最新版1.2.8 2021-10-10 09:46:21 +08:00
RuoYi
ebd7fd59d0 升级element-ui到最新版本2.15.6 2021-10-09 11:54:18 +08:00
RuoYi
c20c2c221f 导入模板标题默认空参数 2021-10-09 11:53:36 +08:00
RuoYi
ee33dbdc0e 升级sass-loader到最新版本10.1.1 2021-09-27 19:06:57 +08:00
RuoYi
5d8d4fa530 升级dart-sass到版本1.32.13 2021-09-27 19:06:43 +08:00
RuoYi
2021028cad 升级file-saver到最新版本2.0.5 2021-09-27 19:06:23 +08:00
RuoYi
7fcb1b2e0a 新增通用方法简化下载使用 2021-09-27 12:10:39 +08:00
RuoYi
f4a2f909a7 Excel注解支持导入导出标题信息 2021-09-26 09:03:28 +08:00
RuoYi
328630fe5d 修复xss过滤后格式出现的异常 2021-09-25 17:16:42 +08:00
RuoYi
f7ae7e29d1 修正代码生成编辑页面单词拼写错误 2021-09-24 14:56:08 +08:00
RuoYi
e46ea3ebac 自动生成代码漏掉 this.#[[$modal]]# 2021-09-24 14:55:11 +08:00
RuoYi
d565fa4883 升级springcloud到最新版2020.0.4 2021-09-24 09:54:05 +08:00
RuoYi
a627108dfe 升级fastjson到最新版1.2.78 2021-09-24 09:53:31 +08:00
RuoYi
829451f05e 新增通用方法简化模态/缓存使用 2021-09-23 09:59:17 +08:00
RuoYi
cae41a8da2 新增通用方法简化模态/缓存使用 2021-09-23 09:35:59 +08:00
RuoYi
a4099cf645 Excel注解支持自定义数据处理器 2021-09-22 09:06:51 +08:00
RuoYi
0a104689ed Excel注解支持自定义数据处理器 2021-09-22 09:03:21 +08:00
RuoYi
97d0226c78 升级spring-boot-admin到最新版2.5.1 2021-09-18 21:34:55 +08:00
RuoYi
3a04dda55d 升级spring-boot到最新版本2.5.4 2021-09-18 21:34:31 +08:00
RuoYi
94310c4f3d 代码生成点击预览重置激活tab 2021-09-18 21:20:45 +08:00
RuoYi
39e7d8a84b 优化aop语法 使用spring自动注入注解 基于注解拦截的aop注解不可能为空 2021-09-18 21:20:18 +08:00
RuoYi
e1037ac125 Cron表达式生成器关闭时销毁,避免再次打开时存在上一次修改的数据 2021-09-18 21:19:52 +08:00
RuoYi
a10384c009 使用vue-data-dict简化数据字典使用 2021-09-17 15:43:02 +08:00
RuoYi
ab8215d1ce 日志注解新增是否保存响应参数 2021-09-16 16:19:23 +08:00
RuoYi
524982c7bd 禁用el-tag组件的渐变动画 2021-09-16 16:19:11 +08:00
RuoYi
d6188aa009 修复后端主子表代码模板方法名生成错误问题 2021-09-16 16:18:48 +08:00
RuoYi
7e8b08a58c 修复多图组件验证失败被删除问题 2021-09-10 11:08:23 +08:00
RuoYi
14771f0ab4 修复代码生成页面数据编辑保存之后总是跳转第一页的问题 2021-09-08 11:29:20 +08:00
RuoYi
97c0603269 优化提示 2021-09-08 11:28:54 +08:00
RuoYi
a58c430858 菜单管理支持配置路由参数 2021-09-08 10:04:23 +08:00
RuoYi
cd4119b26a 修正单词拼写错误 2021-09-08 09:31:37 +08:00
RuoYi
ea20fa3ce2 页签新增关闭左侧 2021-09-05 13:28:32 +08:00
RuoYi
3b54208ac9 页签右键按钮添加图标 2021-09-05 13:27:20 +08:00
RuoYi
d2de744c3f 菜单&部门新增展开/折叠功能 2021-09-04 12:21:33 +08:00
RuoYi
655249d67a 新增暗色菜单风格主题 2021-09-04 12:21:18 +08:00
RuoYi
80a890549d 修复保存配置主题颜色失效问题 2021-09-03 16:52:14 +08:00
RuoYi
5da1979ce6 自定义弹层溢出滚动样式 2021-09-03 13:28:37 +08:00
RuoYi
642512aa91 定时任务支持在线生成cron表达式 2021-09-03 09:53:26 +08:00
RuoYi
4a32a8e725 代码生成导入表按创建时间排序 2021-09-03 09:52:49 +08:00
RuoYi
bb30ae7086 防止表格最后页最后项删除变成暂无数据 2021-09-02 10:46:16 +08:00
RuoYi
34a6f2e1f1 查询列表设置数据字典样式回显 2021-09-01 14:03:59 +08:00
RuoYi
0e51d1e7b1 根据用户ID查询菜单条件加别名 2021-08-30 17:08:55 +08:00
RuoYi
40bdf7b100 修复字典组件值为整形不显示问题 2021-08-29 17:39:43 +08:00
RuoYi
57f51249b6 验证码默认20s超时 2021-08-29 17:39:25 +08:00
RuoYi
dcc5dc0d16 修复带utc日期格式 yyyy-MM-dd'T'HH:mm:ss.SSS 在safari浏览器中无法正确格式化的问题 2021-08-29 17:39:10 +08:00
RuoYi
e87a818706 添加日期范围支持重复添加多组日期范围 2021-08-29 17:38:36 +08:00
RuoYi
67df97d5a7 修改时检查用户数据权限范围 2021-08-24 16:24:25 +08:00
RuoYi
3f8fd0a0f8 定时任务对检查异常进行事务回滚 2021-08-24 11:19:09 +08:00
RuoYi
961fe9a5f1 自定义可拖动弹窗宽高指令 2021-08-20 21:25:53 +08:00
RuoYi
22f156bbb7 补充定时任务表字段注释 2021-08-20 11:07:38 +08:00
RuoYi
22c22c4246 定时任务屏蔽ldap远程调用 2021-08-19 15:34:13 +08:00
RuoYi
994cd62c7a 删掉此处代码,使右边栏动画生效。 2021-08-19 15:32:01 +08:00
RuoYi
1e4ed04a65 优化异常信息 2021-08-16 22:26:29 +08:00
RuoYi
139b25639e 日期范围支持添加多组 2021-08-16 22:26:20 +08:00
RuoYi
13800738cb 修改Dashboard名称 2021-08-16 22:25:09 +08:00
RuoYi
98c538c9e3 默认首页使用keep-alive缓存 2021-08-13 16:41:56 +08:00
RuoYi
0e7c45173c 代码生成主子表多选行数据 2021-08-13 16:41:41 +08:00
RuoYi
132b23dc33 补充遗漏的@Override注解 2021-08-13 16:37:47 +08:00
RuoYi
c3f1dd846c update bin 2021-08-13 16:32:40 +08:00
RuoYi
7b7abde756 添加新群号:201705537 2021-08-08 19:55:51 +08:00
RuoYi
aeeb0eb26b 字典工具类更换路径 2021-08-06 17:52:44 +08:00
RuoYi
265a181891 http请求默认外链打开 2021-08-06 17:02:37 +08:00
RuoYi
22663e1b43 升级element-ui到最新版本2.15.5 2021-08-06 14:33:23 +08:00
RuoYi
24be1a436e 若依 3.1.0 2021-08-01 09:01:15 +08:00
RuoYi
370c53edfa 文件服务本地资源允许跨域访问 2021-07-31 21:51:40 +08:00
RuoYi
f112133ddf 是否开启用户注册功能sql脚本 2021-07-31 21:49:44 +08:00
RuoYi
93ee021b6e XSS过滤排除非json类型 2021-07-31 12:18:24 +08:00
RuoYi
e57d2ea17c 升级nacos到最新版2.0.3 2021-07-31 09:54:28 +08:00
RuoYi
ea038a5437 优化代码生成模板 2021-07-30 22:33:09 +08:00
RuoYi
329aa68644 新增是否开启用户注册功能 2021-07-30 20:03:59 +08:00
Ricky
887430874d 优化代码生成 2021-07-30 18:41:46 +08:00
Ricky
52f8693e1d 优化代码生成 2021-07-30 18:35:52 +08:00
RuoYi
8057dcc4fc 定时任务屏蔽http(s)远程调用 2021-07-30 11:06:11 +08:00
RuoYi
66e0f9a53d 启用部门状态排除顶级节点 2021-07-30 11:05:54 +08:00
RuoYi
7a35c474d6 统一网关错误码响应 2021-07-29 14:51:27 +08:00
RuoYi
892065003d 修复导出含params属性对象参数问题 2021-07-29 10:38:34 +08:00
RuoYi
ede8353503 升级common-pool到最新版本2.10.0 2021-07-28 20:34:41 +08:00
RuoYi
60796ca8fb rollback pr 2021-07-28 20:33:46 +08:00
RuoYi
25e9112ccc 升级minio到最新版本8.2.2 2021-07-28 20:12:50 +08:00
RuoYi
f6c5c91eb1 升级commons.io到最新版本v2.11.0 2021-07-28 14:00:32 +08:00
若依
740da06972 !91 【轻量级PR】 [SysUser] 返回给前端数据的时候,隐藏密码和加盐,防止别人猜测加密方式 或者 暴力破击
Merge pull request !91 from dazer007/master
2021-07-28 05:51:09 +00:00
RuoYi
2a363f9c17 升级tobato到最新版本1.27.2 2021-07-28 13:33:49 +08:00
RuoYi
3c649a8814 升级minio到最新版本8.3.0 2021-07-28 13:30:46 +08:00
RuoYi
a144bf2bff 升级dynamic-ds到最新版本3.4.1 2021-07-28 13:28:50 +08:00
RuoYi
83ee4223be 升级spring-boot-mybatis到最新版2.2.0 2021-07-28 13:24:29 +08:00
RuoYi
8f6c864e96 升级spring-boot-admin到最新版2.4.3 2021-07-28 13:19:50 +08:00
RuoYi
12209ae5a4 升级spring-boot到最新版本2.5.3 2021-07-28 13:17:20 +08:00
duandazhi
4e0301a7b2 [SysUser] 返回给前端数据的时候,隐藏密码和加盐,防止别人猜测加密方式 或者 暴力破击 2021-07-28 13:07:06 +08:00
RuoYi
00fa1c3158 支持配置XSS跨站脚本过滤 2021-07-28 13:05:18 +08:00
若依
04edd66199 !90 【轻量级PR】SysUserController remove 解决把自己删除的bug
Merge pull request !90 from dazer007/secerity-fix-remove-self-ok
2021-07-28 05:01:49 +00:00
若依
d8896c9054 !89 update ruoyi-ui/src/utils/zipdownload.js.
Merge pull request !89 from ytzjf/N/A
2021-07-28 05:01:46 +00:00
duandazhi
dd70c1950e sysuercontroller remove self 问题修复 2021-07-28 10:24:14 +08:00
RuoYi
954d208ac6 支持配置XSS跨站脚本过滤 2021-07-28 09:58:59 +08:00
ytzjf
98d25fa16e update ruoyi-ui/src/utils/zipdownload.js.
BLOB下载时清除URL对象引用
2021-07-28 01:57:11 +00:00
RuoYi
3af7af265b 验证码配置 2021-07-27 20:47:57 +08:00
RuoYi
436c2154ad 支持配置验证码开关&类型 2021-07-27 20:39:46 +08:00
RuoYi
42e8baa85c 添加新群号 2021-07-27 20:38:30 +08:00
RuoYi
0dff71bd4d 跳转路由高亮相对应的菜单栏 2021-07-27 13:09:30 +08:00
RuoYi
20ce9da509 修复任意账户越权问题 2021-07-27 13:08:37 +08:00
RuoYi
a044b0d205 升级element-ui到最新版本2.15.3 2021-07-26 10:11:08 +08:00
RuoYi
698200ecc2 角色&菜单新增字段属性提示信息 2021-07-26 10:10:39 +08:00
RuoYi
883d89ee0b 内链设置meta信息 2021-07-26 10:08:42 +08:00
RuoYi
fb9a480f3c 密码框新增显示切换密码图标 2021-07-26 10:08:28 +08:00
RuoYi
e288710251 导入用户样式调整 2021-07-26 10:06:08 +08:00
RuoYi
1019aa58ce 顶部菜单样式调整 2021-07-26 10:03:52 +08:00
RuoYi
e9621469b2 更多操作按钮添加权限控制 2021-07-25 11:47:55 +08:00
RuoYi
57c4910605 富文本新增上传文件大小限制 2021-07-25 11:39:12 +08:00
RuoYi
9920957796 状态码401返回Promise.reject 2021-07-25 11:36:31 +08:00
RuoYi
e798f46876 顶部菜单排除隐藏的默认路由 2021-07-24 19:15:16 +08:00
RuoYi
caa7537607 修复定时任务日志执行状态显示 2021-07-17 16:51:37 +08:00
若依
8b23c97fdb !83 【轻量级PR】RuoYiFileApplication 重命名为RuoYiFileApplication
Merge pull request !83 from dazer007/RuoYFileApplication-rename-
2021-07-17 08:48:40 +00:00
duandazhi
af49ad54f6 RuoYFileApplication-rename 2021-07-16 12:26:07 +08:00
RuoYi
816479e092 定时任务新增更多操作 2021-07-15 17:36:14 +08:00
RuoYi
7e72849d05 修复多图时无法删除相应图片问题 2021-07-13 10:32:48 +08:00
RuoYi
99206a5d65 删除富文本video事件 2021-07-13 10:32:23 +08:00
RuoYi
114c9f3af6 菜单路由配置支持内链访问 2021-07-11 19:30:24 +08:00
RuoYi
e14fb70c26 自定义弹窗拖拽指令 2021-07-09 21:14:16 +08:00
RuoYi
201149a131 富文本默认上传返回url类型 2021-07-09 21:13:54 +08:00
RuoYi
2bc80c4c07 授权用户添加事务 2021-07-09 21:13:09 +08:00
RuoYi
ee7607bcca 全局注册通用组件 2021-07-09 21:12:37 +08:00
RuoYi
7e2dbc5608 ImageUpload组件支持多图片上传 2021-07-09 21:11:07 +08:00
RuoYi
8eac239e48 FileUpload组件支持多文件上传 2021-07-09 21:10:08 +08:00
若依
6650397e38 !79 【轻量级 PR】:修改登录失效返回值code401
Merge pull request !79 from bug制造者/master
2021-07-09 12:57:28 +00:00
bug制造者
1ca4c26d81 修改登录失效返回值code401
之前返回的code200,前端就会$message一下错误信息,不会弹出401重新登录跳转的弹框。
2021-07-07 09:16:05 +00:00
RuoYi
0b0da91139 角色管理新增分配用户功能 2021-07-06 14:02:37 +08:00
RuoYi
3d47ec2e73 用户管理新增分配角色功能 2021-07-02 10:59:22 +08:00
RuoYi
1f21102204 升级pagehelper到最新版1.3.1 2021-06-25 17:42:41 +08:00
RuoYi
58b4600144 用户信息长度校验限制 2021-06-25 17:41:40 +08:00
RuoYi
6146d63f2c 修复日志列表取消字段排序时的报错问题 2021-06-25 17:40:05 +08:00
RuoYi
dbf42739ca 全局挂载字典标签组件 2021-06-25 17:39:43 +08:00
Ricky
57f56c2769 增加字典标签样式回显 2021-06-22 14:47:28 +08:00
RuoYi
5c130cfda6 封装iframe组件 2021-06-17 20:19:31 +08:00
RuoYi
df284ff6f5 日志列表支持排序操作 2021-06-17 20:18:59 +08:00
RuoYi
1b7550f9a2 升级commons.fileupload到最新版本v1.4 2021-06-16 10:06:09 +08:00
RuoYi
195df24b4b 升级commons.io到最新版本v2.10.0 2021-06-16 10:05:53 +08:00
RuoYi
68de85aa5f 升级nacos到最新版2.0.2 2021-06-15 10:42:03 +08:00
RuoYi
8b6784d8e2 升级element-ui到最新版本2.15.2 2021-06-15 10:41:31 +08:00
RuoYi
b73c14400c 升级spring-boot到最新版本2.5.1 2021-06-12 14:05:27 +08:00
RuoYi
54922af7db 升级dynamic-ds到最新版本3.4.0 2021-06-12 14:05:07 +08:00
RuoYi
23944b2f9c 系统布局配置支持动态标题开关 2021-06-11 11:04:06 +08:00
RuoYi
9d0240b831 分页组件新增pagerCount属性 2021-06-11 11:03:54 +08:00
RuoYi
1aef90d506 修复用户搜索分页变量错误 2021-06-11 11:03:33 +08:00
RuoYi
41b7e62b02 优化部门父级启用状态 2021-06-11 10:49:26 +08:00
RuoYi
70a5e47b66 若依 3.0.0 2021-06-10 09:19:42 +08:00
RuoYi
8722e184d6 升级swagger到最新版本v3.0.0 2021-06-08 20:03:37 +08:00
RuoYi
819ad04e3e 优化Excel导入增加空行判断 2021-06-08 19:55:09 +08:00
RuoYi
ab89a5efcc 富文本工具栏配置视频 2021-06-03 13:58:05 +08:00
RuoYi
2fbb10bfd2 修复导出角色数据范围翻译缺少仅本人 2021-06-03 13:57:52 +08:00
RuoYi
3fba7d5d92 开启nacos/gRpc端口 2021-06-03 13:56:21 +08:00
RuoYi
d8d8758cfa 修复关闭confirm提示框控制台报错问题 2021-06-03 13:55:22 +08:00
RuoYi
5ba3e031f2 升级springcloud到最新版2020.0.3 2021-06-03 10:35:47 +08:00
若依
cc658b9ece !66 代码生成优化
Merge pull request !66 from 雪忆天堂/N/A
2021-06-03 10:35:16 +08:00
RuoYi
1ed627798e 修复表单构建选择下拉选择控制台报错问题 2021-06-02 21:39:43 +08:00
RuoYi
bc4c7a02d3 菜单权限标识长度限制100 2021-06-02 21:39:31 +08:00
RuoYi
17493a2a15 优化图片工具类读取文件 2021-06-02 12:00:20 +08:00
RuoYi
63d7e816ff 添加docker支持 2021-06-02 09:58:36 +08:00
RuoYi
fc7bd9a35d 升级nacos到最新版2.0.1 性能提升 2021-05-31 14:53:50 +08:00
RuoYi
7ebcb4bf8a 修复升级cloud引起的代码生成报错 2021-05-30 18:20:35 +08:00
RuoYi
67feb9947e 优化参数&字典缓存操作 2021-05-27 21:13:48 +08:00
RuoYi
af479c7838 修复两处存在SQL注入漏洞问题 2021-05-27 21:13:01 +08:00
RuoYi
2f3949d732 升级Spring Cloud相关组件到最新版 2021-05-27 09:46:19 +08:00
RuoYi
79c8b17bee Redis设置HashKey序列化 2021-05-26 10:58:57 +08:00
RuoYi
12d3e3d0d8 新增IE浏览器版本过低提示页面 2021-05-26 10:57:11 +08:00
RuoYi
fc33d88334 去除job多余的Serializable 2021-05-26 10:56:26 +08:00
RuoYi
09b49f46e8 升级fastjson到最新版1.2.76 2021-05-26 10:55:34 +08:00
RuoYi
379ea3f6bc 升级druid到最新版本v1.2.6 2021-05-26 10:53:36 +08:00
RuoYi
84b975ac7f 修复请求形参未传值记录日志异常问题 2021-05-26 10:52:38 +08:00
RuoYi
c7b6858433 修正方法名单词拼写错误 2021-05-26 10:47:43 +08:00
RuoYi
33bae9509b 修正mapper模板注释 2021-05-26 10:46:10 +08:00
雪忆天堂
d0cc511bbc 代码生成优化 2021-05-25 16:27:41 +08:00
RuoYi
d855fd67b4 删除操作日志记录日志 2021-05-11 16:52:21 +08:00
RuoYi
7f802e8274 树级结构更新子节点使用replaceFirst 2021-05-11 16:52:07 +08:00
RuoYi
b48e6fb19a 修正代码生成导入表权限标识 2021-04-26 18:19:38 +08:00
若依
de4dd01d97 !61 优化注释
Merge pull request !61 from mask/master
2021-04-26 18:14:25 +08:00
RuoYi
d04a93d75d 修复开启TopNav后,左侧打开外链问题 2021-04-21 16:33:05 +08:00
Mask
fb8eac7064 优化注释 2021-04-21 16:31:21 +08:00
RuoYi
f26c32881c 修复一级菜单包屑显示重复问题 2021-04-21 15:49:16 +08:00
Ricky
2419815bc1 优化ExcelUtil空值处理 2021-04-21 09:59:06 +08:00
RuoYi
cb9fa33b5a 主题颜色保存配置 2021-04-19 17:05:20 +08:00
RuoYi
eb69f8e614 过滤BindingResult对象,防止异常 2021-04-18 22:32:19 +08:00
RuoYi
1eb9581d36 兼容顶部栏一级菜单内部跳转 2021-04-18 22:31:30 +08:00
RuoYi
7789620a15 修正模板字符编码 2021-04-18 22:31:03 +08:00
RuoYi
c3ba1a092c 升级mybatis到最新版2.1.4 2021-04-18 22:30:07 +08:00
Ricky
3ef167e416 优化树表代码生成模板 2021-04-15 10:51:03 +08:00
RuoYi
8e1a9a2433 固定顶部导航栏&窗口大小改变实时更新栏数 2021-04-14 11:02:43 +08:00
RuoYi
cd73787dc7 数据监控默认地址修改 2021-04-13 18:14:53 +08:00
RuoYi
1624a63cff 恢复tansParams方法 2021-04-13 15:36:05 +08:00
RuoYi
db4a8b0e90 布局设置支持保存&重置配置 2021-04-13 15:10:33 +08:00
RuoYi
d989e4a717 富文本编辑器支持自定义上传地址 2021-04-13 15:08:07 +08:00
RuoYi
a664602e28 优化代码生成导出模板名称 2021-04-13 14:54:54 +08:00
RuoYi
f44b453d76 优化主子表代码生成模板 2021-04-13 14:53:50 +08:00
RuoYi
1298d02379 新增菜单导航显示风格TopNav(false为左侧导航菜单,true为顶部导航菜单) 2021-04-12 10:20:25 +08:00
RuoYi
92a93f7cf8 修正通知公告日志记录类型 2021-04-12 10:19:13 +08:00
RuoYi
94a6a5a7d9 页签新增关闭右侧 2021-04-10 21:24:28 +08:00
RuoYi
2ca3f9b640 修复树表数据显示不全&加载慢问题 2021-04-09 10:36:09 +08:00
RuoYi
286bedaa40 删除多余的初始字典数据 2021-04-08 22:21:06 +08:00
RuoYi
edd1cfaf43 Merge branch 'master' of https://gitee.com/y_project/RuoYi-Cloud 2021-04-08 22:19:54 +08:00
RuoYi
accd7ebc93 修改主题后mini类型按钮无效问题 2021-04-08 22:19:43 +08:00
RuoYi
b7b755f0c6 通用下载完成后删除节点 2021-04-08 22:19:16 +08:00
RuoYi
87fcfe0c56 优化注释 2021-04-08 22:19:05 +08:00
RuoYi
89a9188dd4 用户&角色单条删除时使其逻辑删除 2021-04-08 22:18:18 +08:00
若依
45b0e82432 !58 取消了druid的wall配置
Merge pull request !58 from 啦啦啦少年/master
2021-04-08 22:17:16 +08:00
liuxingxing
5d3125463c druid 配置了wall 2021-04-06 15:35:40 +08:00
RuoYi
1ab84cb0e5 修复firefox下表单构建拖拽会新打卡一个选项卡 2021-03-30 17:46:43 +08:00
RuoYi
e58c159225 添加新群号 2021-03-29 18:15:44 +08:00
若依
2edb885ae5 !55 页面超链接修改
Merge pull request !55 from 零度/master
2021-03-25 17:27:57 +08:00
lingdu
b037ee9caf 页面源码地址修改,页面文档地址修改 2021-03-24 21:48:00 +08:00
RuoYi
27d137a4ae 显隐列初始默认隐藏列 2021-03-24 17:33:44 +08:00
RuoYi
25f94db9c5 关闭用户头像上传窗口时恢复原图 2021-03-24 17:33:29 +08:00
RuoYi
457ec516f7 个人信息添加手机&邮箱重复验证 2021-03-21 11:09:44 +08:00
若依
29cd58d3f4 !53 修复异步操作导致的request null,IP获取错误
Merge pull request !53 from TwelveT/N/A
2021-03-20 08:59:05 +08:00
TwelveT
262d06ea3a 修复异步操作导致的request null,IP获取错误 2021-03-19 14:46:06 +08:00
RuoYi
0f733b89dc 通用Controller添加响应返回消息 2021-03-16 16:27:34 +08:00
RuoYi
265b680a61 调整sql默认为当前时间 2021-03-16 16:27:09 +08:00
若依
2b7bb59d12 !49 修复Byte[]类型参数死循环的问题
Merge pull request !49 from 周艺峰/master
2021-03-14 22:07:45 +08:00
RuoYi
41fa57d778 velocity剔除commons-collections版本,防止3.2.1版本的反序列化漏洞 2021-03-14 21:53:51 +08:00
若依
6ad1df166b !51 增加feign客户端IP头部信息
Merge pull request !51 from TwelveT/N/A
2021-03-14 21:31:40 +08:00
TwelveT
24e7ed38a5 增加feign客户端IP头部信息 2021-03-07 23:47:43 +08:00
RuoYi
fd0e9202d8 seata-boot-starter替换为cloud-alibaba-seata 2021-03-07 20:26:59 +08:00
RuoYi
0922410a22 富文本编辑组件支持只读 2021-03-07 15:21:48 +08:00
RuoYi
4edaa14e28 删除多余的代码 2021-03-07 15:21:33 +08:00
周艺峰
a2dede8448 修复Byte[]类型参数死循环的问题 2021-03-04 09:28:51 +08:00
RuoYi
dc83ba0356 更新脚本&优化代码 2021-02-28 21:33:50 +08:00
JuJu
60c815ab76 修复部分更新方法过滤失败与单*匹配不精确问题 2021-02-28 17:21:02 +08:00
DokiYoloo
48cf4250b4 修复AuthFilter白名单过滤匹配不精准 2021-02-25 23:35:22 +08:00
RuoYi
ede8456ea0 修复网关黑名单过滤器中文乱码问题 2021-02-23 18:05:41 +08:00
RuoYi
4dc51fae53 修正注释 2021-02-23 10:27:54 +08:00
RuoYi
192f58e690 修改ip字段长度防止ipv6地址长度不够 2021-02-10 12:53:25 +08:00
RuoYi
852b32eabb 角色非自定义权限范围清空选择值 2021-02-06 10:35:44 +08:00
RuoYi
5e167eb6e1 修复四级菜单无法显示问题 2021-02-06 09:33:45 +08:00
RuoYi
31aefd15f7 若依 2.5.0 2021-02-02 13:31:07 +08:00
RuoYi
716405d22b update README.md 2021-02-02 11:40:58 +08:00
RuoYi
3c33fe21fa 升级spring-boot-alibaba到最新版2.2.5 2021-02-02 11:38:53 +08:00
DokiYoloo
e1e05b761a !43 角色管理-编辑角色-功能权限显示异常
Merge pull request !43 from wihi/master
2021-01-30 17:19:23 +08:00
wanghuan
1804d4fce6 修复角色管理-编辑角色-功能权限显示异常 2021-01-30 16:35:11 +08:00
RuoYi
0dcc955ced 更换过期的共享配置属性 2021-01-27 18:00:50 +08:00
RuoYi
53076612f8 增加分布式事务seata支持 2021-01-27 10:47:01 +08:00
RuoYi
f0f2cde0f9 update swagger 2021-01-26 10:52:31 +08:00
若依
0546504cae !39 修复sentinel流量告警无提示
Merge pull request !39 from 9527/master
2021-01-26 10:50:09 +08:00
RuoYi
17652c3a2f 升级element-ui到最新版本2.15.0 2021-01-24 12:07:17 +08:00
ysj
e96d12975f 修复sentinel流量告警前端不响应 2021-01-21 10:06:29 +08:00
RuoYi
a9b51070ed 添加启动执行脚本 2021-01-17 12:06:33 +08:00
若依
a8c7b9102b !38 返回绝对路径
Merge pull request !38 from xlongwei/N/A
2021-01-17 12:02:21 +08:00
xlongwei
ca04b583a9 返回绝对路径 2021-01-16 13:25:39 +08:00
RuoYi
99390fda05 update README.md 2021-01-14 13:22:53 +08:00
RuoYi
be12108139 修复生成树表代码异常 2021-01-13 17:53:28 +08:00
RuoYi
1dec234174 升级spring-boot到最新版本2.3.7 2021-01-13 17:46:26 +08:00
RuoYi
3fc684b346 升级spring-cloud到Hoxton.SR9 2021-01-13 17:45:30 +08:00
RuoYi
12d8add3e4 升级spring-boot-admin到最新版2.3.1 2021-01-13 17:43:49 +08:00
RuoYi
372b77c662 升级fastjson到最新版1.2.75 2021-01-13 17:24:26 +08:00
RuoYi
5891960756 代码生成模板支持主子表 2021-01-08 11:08:59 +08:00
RuoYi
c5899bfbf0 修复导入数据为负浮点数时丢失精度问题 2021-01-08 11:08:43 +08:00
RuoYi
4125f44179 用户显隐列添加不同key防止被复用 2021-01-07 13:37:33 +08:00
RuoYi
09a0058379 表格右侧工具栏组件支持显隐列 2021-01-06 17:50:01 +08:00
RuoYi
3fdcac939a 升级druid到最新版本v1.2.4 2021-01-06 12:01:05 +08:00
RuoYi
4cc4e8a8fa 编码解码用户名,防止中文出现乱码 2021-01-06 12:00:41 +08:00
RuoYi
dee4653b9b 代码生成支持文件上传组件 2021-01-06 11:59:13 +08:00
若依
2c610dc465 !37 update ruoyi-ui/src/components/FileUpload/index.vue.
Merge pull request !37 from ouwei2020/N/A
2021-01-06 11:57:57 +08:00
ouwei2020
2c323ca3ff update ruoyi-ui/src/components/FileUpload/index.vue. 2021-01-06 11:09:23 +08:00
DokiYolo
a95be9d418 解决header获取username中文情况下乱码 2021-01-06 10:06:57 +08:00
RuoYi
a445462153 代码生成支持文件上传组件 2021-01-05 21:34:27 +08:00
RuoYi
843f08984b 图片组件添加预览&移除功能 2021-01-05 21:08:01 +08:00
RuoYi
2b3820223c 修复IE11浏览器报错问题 2021-01-05 10:30:05 +08:00
RuoYi
a5d0028b39 操作按钮组调整为朴素按钮样式 2021-01-05 10:20:26 +08:00
RuoYi
449704180b Update copyright 2021-01-04 17:54:40 +08:00
JuJu
8a18873b81 修正操作日志删除接口路径 2021-01-01 12:47:46 +08:00
JuJu
199228f6cb spring.factories增加RemoteFileFallbackFactory 2021-01-01 12:41:28 +08:00
RuoYi
6d0b4f5d16 用户手机邮箱&菜单组件修改允许空字符串 2020-12-29 17:29:22 +08:00
RuoYi
4cc0e2650c 代码生成数据库文本类型生成表单文本域 2020-12-29 11:27:58 +08:00
RuoYi
06074571f5 Excel注解支持Image图片导出 2020-12-27 10:05:28 +08:00
RuoYi
2698ea58d4 代码生成日期控件区分范围 2020-12-25 09:36:22 +08:00
RuoYi
8c9eb7d6b6 修正侧边栏静态路由丢失问题 2020-12-24 19:33:09 +08:00
RuoYi
79472708d9 防止get请求参数值为false或0等特殊值会导致无法正确的传参 2020-12-22 16:25:16 +08:00
RuoYi
586908b4d7 若依 2.4.0 2020-12-22 10:40:42 +08:00
RuoYi
a7bac940a6 若依 2.4.0 2020-12-22 10:21:29 +08:00
RuoYi
e100b0b940 增加分布式文件Minio支持 2020-12-22 09:30:07 +08:00
DokiYoloo
161a6249e9 权限工具类增加admin判断 2020-12-21 19:11:25 +08:00
RuoYi
e4a6e5ef19 支持多数据源切换 2020-12-21 16:32:00 +08:00
RuoYi
7ceb5c3c8f 优化多级菜单之间切换无法缓存的问题 2020-12-21 11:13:35 +08:00
RuoYi
bfd33f2412 移除path-to-regexp正则匹配插件 2020-12-17 12:07:26 +08:00
RuoYi
2ddf834552 优化多级菜单之间切换无法缓存的问题 2020-12-16 22:19:30 +08:00
RuoYi
743e59db7a README 2020-12-15 10:15:27 +08:00
RuoYi
88aff5d8a7 登录后push添加catch防止出现检查错误 2020-12-15 10:15:06 +08:00
JuJu
dbeded1c09 修复导出时携带params空对象导致转换错误 2020-12-14 16:09:15 +08:00
DokiYoloo
e4b8898d0d !30 修正代码生成下载zip路径
Merge pull request !30 from 我啊/master
2020-12-14 14:41:00 +08:00
isme
62d7ce5aa9 修复代码生成路径错误 2020-12-14 14:38:31 +08:00
RuoYi
7fd4860ff2 调整代码生成页列宽 2020-12-13 17:08:51 +08:00
RuoYi
ff979772fe 修改Set可能导致嵌套的问题 2020-12-13 17:08:30 +08:00
RuoYi
dddbaeb5c0 代码生成预览支持高亮显示 2020-12-11 18:01:44 +08:00
RuoYi
3c5893074b 去除用户手机邮箱部门必填验证 2020-12-11 17:40:28 +08:00
RuoYi
2cde98a01b 日志记录增加过滤多文件场景 2020-12-11 17:24:31 +08:00
RuoYi
22a825718f 项目添加robots.txt 防止系统被搜索引擎收录 2020-12-10 18:42:44 +08:00
RuoYi
a0bcaab926 前端更新插件版本 2020-12-10 18:37:44 +08:00
RuoYi
1c023fbe7c 升级vue-router到最新版本3.4.9 2020-12-10 11:28:27 +08:00
RuoYi
81bf4d28ef 代码生成预览提供滚动机制 2020-12-10 11:27:52 +08:00
RuoYi
963d2a0443 代码生成预览溢出提供滚动机制 2020-12-09 10:34:53 +08:00
RuoYi
10de0df04e 删除用户和角色解绑关联 2020-12-08 19:37:07 +08:00
RuoYi
1066713524 关闭页签清理缓存数据 2020-12-08 19:35:29 +08:00
RuoYi
bcdf270bb0 回显数据字典防止空值报错 2020-12-08 19:34:52 +08:00
RuoYi
0673eab57e 支持主题风格配置 2020-12-07 14:25:11 +08:00
RuoYi
5094bba352 修改用户头像预览宽高 2020-12-06 17:47:25 +08:00
RuoYi
7523e0475f get请求params添加null值判断 2020-12-06 11:06:32 +08:00
RuoYi
6beb5cadb2 支持get请求映射params参数 2020-12-04 10:53:25 +08:00
RuoYi
5174536744 升级poi到最新版本4.1.2 2020-12-03 13:36:30 +08:00
RuoYi
e526e33030 Excel支持注解align对齐方式 2020-12-03 13:34:04 +08:00
RuoYi
e8b19f863a 防止安全扫描YUI出现的风险提示 2020-12-03 10:27:45 +08:00
RuoYi
91a2f7b16b 获取请求token方法移至权限工具类 2020-11-30 15:09:59 +08:00
RuoYi
3a9d45a7dd 服务之间feign调用传递用户请求头 2020-11-30 12:49:18 +08:00
RuoYi
073d90ed17 设置用户头像悬停高度 2020-11-30 11:08:23 +08:00
RuoYi
689d5b1612 升级element-ui到最新版本v2.14.1 2020-11-30 10:51:10 +08:00
RuoYi
c615248ad6 修正转换字符串的目标字符集属性 2020-11-30 10:50:24 +08:00
RuoYi
20f85a37cf 三级菜单自动配置组件 2020-11-28 21:19:14 +08:00
RuoYi
b199db3822 修复三级菜单之间切换页面无法缓存的问题 2020-11-28 21:08:02 +08:00
RuoYi
f5bf01159a 代码生成删除多余的数字float类型 2020-11-28 13:21:24 +08:00
RuoYi
2c05324108 Excel支持导入Boolean型数据 2020-11-28 13:21:02 +08:00
RuoYi
6b36b32e39 删除多余的依赖 2020-11-25 18:22:57 +08:00
RuoYi
1abf802a09 若依 2.3.0 2020-11-20 08:39:32 +08:00
RuoYi
2bb0eb1edb 增加分布式文件FastDFS支持 2020-11-19 18:51:22 +08:00
RuoYi
1a12d56cc3 优化头像样式,鼠标移入悬停遮罩 2020-11-19 09:33:32 +08:00
RuoYi
45e5395550 README 2020-11-18 20:29:13 +08:00
RuoYi
692cc84693 README 2020-11-18 20:15:17 +08:00
RuoYi
b812e01100 新增文件服务应用 2020-11-18 19:57:55 +08:00
RuoYi
594329127f AjaxResult重写put方法,以方便链式调用 2020-11-18 16:49:01 +08:00
RuoYi
cdc813c453 代码生成支持上传控件 2020-11-17 20:37:41 +08:00
RuoYi
3d7fe2a288 Copyright 2018-2020 2020-11-17 20:36:59 +08:00
RuoYi
93920707b5 新增图片上传组件 2020-11-17 18:57:20 +08:00
RuoYi
84ffdaefe2 调整默认首页 2020-11-07 11:06:22 +08:00
RuoYi
0422f858f7 2020年双十一云服务器优惠,错过又要等一年 2020-11-04 16:59:04 +08:00
RuoYi
01c3019cea 添加新群号 2020-11-04 12:09:11 +08:00
JuJu
24fb0b712a 删除无用代码 2020-10-26 15:39:36 +08:00
JuJu
8fdcd576c9 修正hasRole匹配为equals 2020-10-23 16:00:39 +08:00
JuJu
07df90f99b 修正数组权限为空判断 2020-10-23 15:33:06 +08:00
RuoYi
7bd762267b 删除不必要的代码 2020-10-13 17:58:36 +08:00
RuoYi
512c6acebc 修正注释选中节点和半选节点获取 2020-10-13 17:44:56 +08:00
RuoYi
ad928ee719 升级pagehelper到最新版1.3.0 2020-10-13 17:43:03 +08:00
RuoYi
04d8c97c62 升级fastjson到最新版1.2.74 2020-10-13 17:41:28 +08:00
RuoYi
9fc5d74f6e 使用参数dateRange而非bind在model上的dateRange 2020-10-13 17:40:36 +08:00
RuoYi
f245105b58 修正定时任务执行一次权限标识 2020-10-13 17:39:25 +08:00
RuoYi
c0cc0bdf84 修复页签关闭所有固定标签路由不刷新问题 2020-10-13 17:38:38 +08:00
RuoYi
c04ea0221a 表单构建布局型组件新增按钮 2020-10-13 17:37:12 +08:00
RuoYi
d52f6673bc 调整日志路径到模块目录 2020-10-13 17:36:00 +08:00
RuoYi
dce8ee4236 修正菜单提示信息错误 2020-10-03 10:54:47 +08:00
RuoYi
f64f806a42 若依 2.2 2020-09-30 09:54:59 +08:00
RuoYi
fbbc91ea0a 左侧菜单文字过长显示省略号 2020-09-24 19:22:29 +08:00
RuoYi
c2bd0ace6e 修改用户个人资料/密码同步缓存信息 2020-09-24 16:29:21 +08:00
RuoYi
6b74ea676c 修正文字错误 2020-09-24 16:28:43 +08:00
RuoYi
86c7a763bc 新增在线用户管理 2020-09-24 15:44:43 +08:00
JuJu
3eac04311f Job与Gen增加默认Redis配置 2020-09-24 14:52:42 +08:00
RuoYi
679756c633 菜单新增是否缓存keep-alive 2020-09-24 14:06:19 +08:00
RuoYi
2115edcfb4 菜单新增是否缓存keep-alive 2020-09-21 18:29:44 +08:00
RuoYi
8acb322d49 菜单&数据权限新增(展开/折叠 全选/全不选 父子联动) 2020-09-21 18:10:26 +08:00
RuoYi
f4f89f9de6 代码生成支持同步数据库 2020-09-21 13:25:51 +08:00
RuoYi
5d1701fd69 表格操作列间距调整 2020-09-21 12:35:48 +08:00
RuoYi
fec24d6785 导入excel整形值校验优化 2020-09-21 12:35:32 +08:00
RuoYi
00e2c7f04d 升级Spring Cloud组件到最新版 2020-09-21 12:27:11 +08:00
RuoYi
0e21fab978 token续期调整到后端&默认有效期延长 2020-09-17 12:44:05 +08:00
RuoYi
4ec6d51aca 全局异常处理 2020-09-17 12:08:30 +08:00
RuoYi
15a4a5350d 修复前端通用导出方法参数传值请求方式问题 2020-09-17 11:41:35 +08:00
RuoYi
9277d7173d 代码生成支持富文本控件 2020-09-15 17:21:40 +08:00
RuoYi
35f8665dac 限制系统内置参数不允许删除 2020-09-15 17:12:51 +08:00
RuoYi
8601b26cff 退出登录接口加入白名单&修改过期提示 2020-09-15 17:10:37 +08:00
RuoYi
eda2ec10f4 修复通知公告longblob类型乱码问题 2020-09-13 12:06:59 +08:00
RuoYi
fc48704057 富文本工具栏样式对齐 2020-09-13 12:06:46 +08:00
RuoYi
00345099cf 修正注释图标路径 2020-09-13 12:06:10 +08:00
RuoYi
155b585ae5 Excel导出类型NUMERIC支持精度浮点类型 2020-09-13 12:05:49 +08:00
RuoYi
0ffefeb420 修正调用目标字符串最大长度 2020-09-13 12:05:26 +08:00
RuoYi
dbadce31c6 网关白名单放入nacos配置&支持模糊匹配 2020-09-13 12:00:46 +08:00
RuoYi
857a5b26e7 数据权限中的空值处理 2020-09-04 18:36:58 +08:00
RuoYi
ca97fc0b5d 数据字典缓存空值处理 2020-09-04 18:34:50 +08:00
RuoYi
293b855866 修复Editor组件无法对响应式更新null值问题 2020-09-04 18:32:25 +08:00
RuoYi
f9d537b567 修改自定义权限实现 2020-09-04 18:31:08 +08:00
RuoYi
d42a6751e3 修改公告内容字段类型 2020-09-01 18:08:38 +08:00
RuoYi
f124236a64 remove \ 2020-09-01 16:03:51 +08:00
RuoYi
6704db8108 移除 OAuth2 改为 Redis 2020-09-01 13:31:00 +08:00
RuoYi
179062e6e5 数据权限判断对象类型 2020-08-31 23:25:44 +08:00
RuoYi
397e821824 修正数据库字符串类型nvarchar 2020-08-31 23:24:38 +08:00
RuoYi
6b25828113 优化递归子节点 2020-08-31 23:23:08 +08:00
RuoYi
bd7ae4e96b 代码生成树模板去掉多余双引号 2020-08-31 23:19:29 +08:00
RuoYi
5f5c4e8415 remove pig 2020-08-31 17:55:18 +08:00
RuoYi
66e8b59e26 导出Excel调整targetAttr获取值方法,防止get方法不规范 2020-08-26 15:40:00 +08:00
RuoYi
a7d93d38ce 生成页面时不忽略remark属性 2020-08-26 14:25:41 +08:00
RuoYi
ba3549e824 Excel注解支持自动统计数据总和 2020-08-26 11:44:58 +08:00
RuoYi
e2c4ca4922 终端授权类型改为复选框 2020-08-23 10:51:46 +08:00
RuoYi
1305507bf4 终端设置新增明文安全码 2020-08-22 22:00:50 +08:00
RuoYi
c789ef147d Editor组件优化,支持自定义高度&图片冲突问题 2020-08-22 14:59:44 +08:00
RuoYi
1ffee7ac0b 修改公告内容字段类型 2020-08-22 14:59:04 +08:00
RuoYi
7401297236 Excel注解支持设置BigDecimal精度&舍入规则 2020-08-22 14:56:28 +08:00
RuoYi
6f1dd1125b 升级fastjson到最新版1.2.73 2020-08-22 14:53:27 +08:00
RuoYi
82eeb86d60 代码生成添加select必填选项 2020-08-22 14:52:37 +08:00
RuoYi
f5cee45345 修改sass为node-sass,避免el-icon图标乱码 2020-08-22 14:49:47 +08:00
RuoYi
1524005060 修复根节点为子部门时,树状结构显示问题 2020-08-22 14:47:44 +08:00
RuoYi
b70e8ad81e 表格右侧工具栏组件 2020-08-13 14:11:00 +08:00
RuoYi
a2c265848d 优化上级菜单不能选择自己 2020-08-13 13:52:40 +08:00
RuoYi
19e5f11fd3 修复代码生成下载路径错误 2020-08-13 11:04:55 +08:00
RuoYi
8d99adceb2 唯一限制条件只返回单条数据 2020-08-07 17:32:33 +08:00
RuoYi
f1bc33e80d 唯一限制条件只返回单条数据 2020-08-07 16:42:36 +08:00
RuoYi
6bd7e183f6 修复富文本空格和缩进保存后不生效问题&删除重复的placeholder 2020-08-07 16:39:14 +08:00
RuoYi
7d94113d24 修改Excel设置STRING单元格类型 2020-08-05 13:02:57 +08:00
RuoYi
97ebab0c67 全局异常状态汉化拦截处理 2020-08-03 09:29:26 +08:00
451 changed files with 18419 additions and 6396 deletions

View File

@@ -1,13 +1,17 @@
## 平台简介 ## 平台简介
若依是一套全部开源的快速开发平台,毫无保留给个人及企业免费使用。
* 采用前后端分离的模式,微服务版本前端(基于 [RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue))。 * 采用前后端分离的模式,微服务版本前端(基于 [RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue))。
* 后端采用Spring Boot、Spring Cloud & Alibaba。 * 后端采用Spring Boot、Spring Cloud & Alibaba。
* 注册中心、配置中心选型Nacos权限认证使用OAuth2 * 注册中心、配置中心选型Nacos权限认证使用Redis
* 流量控制框架选型Sentinel。 * 流量控制框架选型Sentinel分布式事务选型Seata
* 提供了技术栈([Vue3](https://v3.cn.vuejs.org) [Element Plus](https://element-plus.org/zh-CN) [Vite](https://cn.vitejs.dev))版本[RuoYi-Cloud-Vue3](https://github.com/yangzongzhuan/RuoYi-Cloud-Vue3),保持同步更新。
* 如需不分离应用,请移步 [RuoYi](https://gitee.com/y_project/RuoYi),如需分离应用,请移步 [RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue) * 如需不分离应用,请移步 [RuoYi](https://gitee.com/y_project/RuoYi),如需分离应用,请移步 [RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue)
* 感谢[ruoyi-cloud-design](https://gitee.com/zhangmrit/ruoyi-cloud)[pig](https://gitee.com/log4j/pig)。 * 阿里云折扣场:[点我进入](http://aly.ruoyi.vip),腾讯云秒杀场:[点我进入](http://txy.ruoyi.vip)  
* 阿里云优惠券:[点我进入](https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link),腾讯云优惠券:[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console)   * 阿里云优惠券:[点我领取](https://www.aliyun.com/minisite/goods?userCode=brki8iof&share_source=copy_link),腾讯云优惠券:[点我领取](https://cloud.tencent.com/redirect.php?redirect=1025&cps_key=198c8df2ed259157187173bc7f4f32fd&from=console)  
#### 友情链接 [若依/RuoYi-Cloud](https://gitee.com/zhangmrit/ruoyi-cloud) Ant Design版本。
## 系统模块 ## 系统模块
@@ -21,6 +25,7 @@ com.ruoyi
├── ruoyi-common // 通用模块 ├── ruoyi-common // 通用模块
│ └── ruoyi-common-core // 核心模块 │ └── ruoyi-common-core // 核心模块
│ └── ruoyi-common-datascope // 权限范围 │ └── ruoyi-common-datascope // 权限范围
│ └── ruoyi-common-datasource // 多数据源
│ └── ruoyi-common-log // 日志记录 │ └── ruoyi-common-log // 日志记录
│ └── ruoyi-common-redis // 缓存服务 │ └── ruoyi-common-redis // 缓存服务
│ └── ruoyi-common-security // 安全模块 │ └── ruoyi-common-security // 安全模块
@@ -29,6 +34,7 @@ com.ruoyi
│ └── ruoyi-system // 系统模块 [9201] │ └── ruoyi-system // 系统模块 [9201]
│ └── ruoyi-gen // 代码生成 [9202] │ └── ruoyi-gen // 代码生成 [9202]
│ └── ruoyi-job // 定时任务 [9203] │ └── ruoyi-job // 定时任务 [9203]
│ └── ruoyi-file // 文件服务 [9300]
├── ruoyi-visual // 图形化管理模块 ├── ruoyi-visual // 图形化管理模块
│ └── ruoyi-visual-monitor // 监控中心 [9100] │ └── ruoyi-visual-monitor // 监控中心 [9100]
├──pom.xml // 公共依赖 ├──pom.xml // 公共依赖
@@ -36,7 +42,7 @@ com.ruoyi
## 架构图 ## 架构图
<img src="https://oscimg.oschina.net/oscnet/up-aaa2d885b0fba37e52b56f0948edde1c4fe.png"/> <img src="https://oscimg.oschina.net/oscnet/up-82e9722ecb846786405a904bafcf19f73f3.png"/>
## 内置功能 ## 内置功能
@@ -79,7 +85,7 @@ com.ruoyi
</tr> </tr>
<tr> <tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-39bf2584ec3a529b0d5a3b70d15c9b37646.png"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-39bf2584ec3a529b0d5a3b70d15c9b37646.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-936ec82d1f4872e1bc980927654b6007307.png"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-4148b24f58660a9dc347761e4cf6162f28f.png"/></td>
</tr> </tr>
<tr> <tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-b2d62ceb95d2dd9b3fbe157bb70d26001e9.png"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-b2d62ceb95d2dd9b3fbe157bb70d26001e9.png"/></td>
@@ -102,12 +108,12 @@ com.ruoyi
<td><img src="https://oscimg.oschina.net/oscnet/up-92ffb7f3835855cff100fa0f754a6be0d99.png"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-92ffb7f3835855cff100fa0f754a6be0d99.png"/></td>
</tr> </tr>
<tr> <tr>
<td><img src="https://oscimg.oschina.net/oscnet/up-d69a19493e5aff7ecdd5d02410862bcea40.png"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-ff9e3066561574aca73005c5730c6a41f15.png"/></td>
<td><img src="https://oscimg.oschina.net/oscnet/up-6d73c2140ce694e3de4c05035fdc1868d4c.png"/></td> <td><img src="https://oscimg.oschina.net/oscnet/up-5e4daac0bb59612c5038448acbcef235e3a.png"/></td>
</tr> </tr>
</table> </table>
## 若依微服务交流群 ## 若依微服务交流群
QQ群 [![加入QQ群](https://img.shields.io/badge/已满-42799195-blue.svg)](https://jq.qq.com/?_wv=1027&k=yqInfq0S) [![加入QQ群](https://img.shields.io/badge/170157040-blue.svg)](https://jq.qq.com/?_wv=1027&k=Oy1mb3p8) 点击按钮入群。 QQ群 [![加入QQ群](https://img.shields.io/badge/已满-42799195-blue.svg)](https://jq.qq.com/?_wv=1027&k=yqInfq0S) [![加入QQ群](https://img.shields.io/badge/已满-170157040-blue.svg)](https://jq.qq.com/?_wv=1027&k=Oy1mb3p8) [![加入QQ群](https://img.shields.io/badge/已满-130643120-blue.svg)](https://jq.qq.com/?_wv=1027&k=rvxkJtXK) [![加入QQ群](https://img.shields.io/badge/已满-225920371-blue.svg)](https://jq.qq.com/?_wv=1027&k=0Ck3PvTe) [![加入QQ群](https://img.shields.io/badge/已满-201705537-blue.svg)](https://jq.qq.com/?_wv=1027&k=FnHHP4TT) [![加入QQ群](https://img.shields.io/badge/236543183-blue.svg)](https://jq.qq.com/?_wv=1027&k=qdT1Ojpz) 点击按钮入群。

View File

@@ -1,6 +1,6 @@
@echo off @echo off
echo. echo.
echo [信息] 清理生成路径。 echo [信息] 清理工程target生成路径。
echo. echo.
%~d0 %~d0

14
bin/run-auth.bat Normal file
View File

@@ -0,0 +1,14 @@
@echo off
echo.
echo [信息] 使用Jar命令运行Auth工程。
echo.
cd %~dp0
cd ../ruoyi-auth/target
set JAVA_OPTS=-Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m
java -Dfile.encoding=utf-8 %JAVA_OPTS% -jar ruoyi-auth.jar
cd bin
pause

14
bin/run-gateway.bat Normal file
View File

@@ -0,0 +1,14 @@
@echo off
echo.
echo [信息] 使用Jar命令运行Gateway工程。
echo.
cd %~dp0
cd ../ruoyi-gateway/target
set JAVA_OPTS=-Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m
java -Dfile.encoding=utf-8 %JAVA_OPTS% -jar ruoyi-gateway.jar
cd bin
pause

14
bin/run-modules-file.bat Normal file
View File

@@ -0,0 +1,14 @@
@echo off
echo.
echo [信息] 使用Jar命令运行Modules-File工程。
echo.
cd %~dp0
cd ../ruoyi-modules/ruoyi-file/target
set JAVA_OPTS=-Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m
java -Dfile.encoding=utf-8 %JAVA_OPTS% -jar ruoyi-modules-file.jar
cd bin
pause

14
bin/run-modules-gen.bat Normal file
View File

@@ -0,0 +1,14 @@
@echo off
echo.
echo [信息] 使用Jar命令运行Modules-Gen工程。
echo.
cd %~dp0
cd ../ruoyi-modules/ruoyi-gen/target
set JAVA_OPTS=-Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m
java -Dfile.encoding=utf-8 %JAVA_OPTS% -jar ruoyi-modules-gen.jar
cd bin
pause

14
bin/run-modules-job.bat Normal file
View File

@@ -0,0 +1,14 @@
@echo off
echo.
echo [信息] 使用Jar命令运行Modules-Job工程。
echo.
cd %~dp0
cd ../ruoyi-modules/ruoyi-job/target
set JAVA_OPTS=-Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m
java -Dfile.encoding=utf-8 %JAVA_OPTS% -jar ruoyi-modules-job.jar
cd bin
pause

View File

@@ -0,0 +1,14 @@
@echo off
echo.
echo [信息] 使用Jar命令运行Modules-System工程。
echo.
cd %~dp0
cd ../ruoyi-modules/ruoyi-system/target
set JAVA_OPTS=-Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m
java -Dfile.encoding=utf-8 %JAVA_OPTS% -jar ruoyi-modules-system.jar
cd bin
pause

14
bin/run-monitor.bat Normal file
View File

@@ -0,0 +1,14 @@
@echo off
echo.
echo [信息] 使用Jar命令运行Monitor工程。
echo.
cd %~dp0
cd ../ruoyi-visual/ruoyi-monitor/target
set JAVA_OPTS=-Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m
java -Dfile.encoding=utf-8 %JAVA_OPTS% -jar ruoyi-visual-monitor.jar
cd bin
pause

67
docker/deploy.sh Normal file
View File

@@ -0,0 +1,67 @@
#!/bin/sh
# 使用说明,用来提示输入参数
usage() {
echo "Usage: sh 执行脚本.sh [port|base|modules|stop|rm]"
exit 1
}
# 开启所需端口
port(){
firewall-cmd --add-port=80/tcp --permanent
firewall-cmd --add-port=8080/tcp --permanent
firewall-cmd --add-port=8848/tcp --permanent
firewall-cmd --add-port=9848/tcp --permanent
firewall-cmd --add-port=9849/tcp --permanent
firewall-cmd --add-port=6379/tcp --permanent
firewall-cmd --add-port=3306/tcp --permanent
firewall-cmd --add-port=9100/tcp --permanent
firewall-cmd --add-port=9200/tcp --permanent
firewall-cmd --add-port=9201/tcp --permanent
firewall-cmd --add-port=9202/tcp --permanent
firewall-cmd --add-port=9203/tcp --permanent
firewall-cmd --add-port=9300/tcp --permanent
service firewalld restart
}
# 启动基础环境(必须)
base(){
docker-compose up -d ruoyi-mysql ruoyi-redis ruoyi-nacos ruoyi-nginx
}
# 启动程序模块(必须)
modules(){
docker-compose up -d ruoyi-gateway ruoyi-auth ruoyi-modules-system
}
# 关闭所有环境/模块
stop(){
docker-compose stop
}
# 删除所有环境/模块
rm(){
docker-compose rm
}
# 根据输入参数,选择执行对应方法,不输入则执行使用说明
case "$1" in
"port")
port
;;
"base")
base
;;
"modules")
modules
;;
"stop")
stop
;;
"rm")
rm
;;
*)
usage
;;
esac

140
docker/docker-compose.yml Normal file
View File

@@ -0,0 +1,140 @@
version : '3.8'
services:
ruoyi-nacos:
container_name: ruoyi-nacos
image: nacos/nacos-server
build:
context: ./nacos
environment:
- MODE=standalone
volumes:
- ./nacos/logs/:/home/nacos/logs
- ./nacos/conf/application.properties:/home/nacos/conf/application.properties
ports:
- "8848:8848"
- "9848:9848"
- "9849:9849"
depends_on:
- ruoyi-mysql
ruoyi-mysql:
container_name: ruoyi-mysql
image: mysql:5.7
build:
context: ./mysql
ports:
- "3306:3306"
volumes:
- ./mysql/conf:/etc/mysql/conf.d
- ./mysql/logs:/logs
- ./mysql/data:/var/lib/mysql
command: [
'mysqld',
'--innodb-buffer-pool-size=80M',
'--character-set-server=utf8mb4',
'--collation-server=utf8mb4_unicode_ci',
'--default-time-zone=+8:00',
'--lower-case-table-names=1'
]
environment:
MYSQL_DATABASE: 'ry-cloud'
MYSQL_ROOT_PASSWORD: password
ruoyi-redis:
container_name: ruoyi-redis
image: redis
build:
context: ./redis
ports:
- "6379:6379"
volumes:
- ./redis/conf/redis.conf:/home/ruoyi/redis/redis.conf
- ./redis/data:/data
command: redis-server /home/ruoyi/redis/redis.conf
ruoyi-nginx:
container_name: ruoyi-nginx
image: nginx
build:
context: ./nginx
ports:
- "80:80"
volumes:
- ./nginx/html/dist:/home/ruoyi/projects/ruoyi-ui
- ./nginx/conf/nginx.conf:/etc/nginx/nginx.conf
- ./nginx/logs:/var/log/nginx
- ./nginx/conf.d:/etc/nginx/conf.d
depends_on:
- ruoyi-gateway
links:
- ruoyi-gateway
ruoyi-gateway:
container_name: ruoyi-gateway
build:
context: ./ruoyi/gateway
dockerfile: dockerfile
ports:
- "8080:8080"
depends_on:
- ruoyi-redis
links:
- ruoyi-redis
ruoyi-auth:
container_name: ruoyi-auth
build:
context: ./ruoyi/auth
dockerfile: dockerfile
ports:
- "9200:9200"
depends_on:
- ruoyi-redis
links:
- ruoyi-redis
ruoyi-modules-system:
container_name: ruoyi-modules-system
build:
context: ./ruoyi/modules/system
dockerfile: dockerfile
ports:
- "9201:9201"
depends_on:
- ruoyi-redis
- ruoyi-mysql
links:
- ruoyi-redis
- ruoyi-mysql
ruoyi-modules-gen:
container_name: ruoyi-modules-gen
build:
context: ./ruoyi/modules/gen
dockerfile: dockerfile
ports:
- "9202:9202"
depends_on:
- ruoyi-mysql
links:
- ruoyi-mysql
ruoyi-modules-job:
container_name: ruoyi-modules-job
build:
context: ./ruoyi/modules/job
dockerfile: dockerfile
ports:
- "9203:9203"
depends_on:
- ruoyi-mysql
links:
- ruoyi-mysql
ruoyi-modules-file:
container_name: ruoyi-modules-file
build:
context: ./ruoyi/modules/file
dockerfile: dockerfile
ports:
- "9300:9300"
volumes:
- ./ruoyi/uploadPath:/home/ruoyi/uploadPath
ruoyi-visual-monitor:
container_name: ruoyi-visual-monitor
build:
context: ./ruoyi/visual/monitor
dockerfile: dockerfile
ports:
- "9100:9100"

View File

@@ -0,0 +1 @@
存放sql目录下的所有脚本用于docker自动执行。

7
docker/mysql/dockerfile Normal file
View File

@@ -0,0 +1,7 @@
# 基础镜像
FROM mysql:5.7
# author
MAINTAINER ruoyi
# 执行sql脚本
ADD ./db/*.sql /docker-entrypoint-initdb.d/

View File

@@ -0,0 +1,32 @@
spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://ruoyi-mysql:3306/ry-config?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user=root
db.password=password
nacos.naming.empty-service.auto-clean=true
nacos.naming.empty-service.clean.initial-delay-ms=50000
nacos.naming.empty-service.clean.period-time-ms=30000
management.endpoints.web.exposure.include=*
management.metrics.export.elastic.enabled=false
management.metrics.export.influx.enabled=false
server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.pattern=%h %l %u %t "%r" %s %b %D %{User-Agent}i %{Request-Source}i
server.tomcat.basedir=
nacos.security.ignore.urls=/,/error,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-ui/public/**,/v1/auth/**,/v1/console/health/**,/actuator/**,/v1/console/server/**
nacos.core.auth.system.type=nacos
nacos.core.auth.enabled=false
nacos.core.auth.default.token.expire.seconds=18000
nacos.core.auth.default.token.secret.key=SecretKey012345678901234567890123456789012345678901234567890123456789
nacos.core.auth.caching.enabled=true
nacos.core.auth.enable.userAgentAuthWhite=false
nacos.core.auth.server.identity.key=serverIdentity
nacos.core.auth.server.identity.value=security
nacos.istio.mcp.server.enabled=false

7
docker/nacos/dockerfile Normal file
View File

@@ -0,0 +1,7 @@
# 基础镜像
FROM nacos/nacos-server
# author
MAINTAINER ruoyi
# 复制conf文件到路径
COPY ./conf/application.properties /home/nacos/conf/application.properties

View File

@@ -0,0 +1,36 @@
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root /home/ruoyi/projects/ruoyi-ui;
try_files $uri $uri/ /index.html;
index index.html index.htm;
}
location /prod-api/{
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://ruoyi-gateway:8080/;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}# requirepass 123456

15
docker/nginx/dockerfile Normal file
View File

@@ -0,0 +1,15 @@
# 基础镜像
FROM nginx
# author
MAINTAINER ruoyi
# 挂载目录
VOLUME /home/ruoyi/projects/ruoyi-ui
# 创建目录
RUN mkdir -p /home/ruoyi/projects/ruoyi-ui
# 指定路径
WORKDIR /home/ruoyi/projects/ruoyi-ui
# 复制conf文件到路径
COPY ./conf/nginx.conf /etc/nginx/nginx.conf
# 复制html文件到路径
COPY ./html/dist /home/ruoyi/projects/ruoyi-ui

1
docker/nginx/html/dist/readme.txt vendored Normal file
View File

@@ -0,0 +1 @@
存放前端ruoyi-ui构建好的静态文件用于nginx请求访问。

View File

@@ -0,0 +1 @@
# requirepass 123456

13
docker/redis/dockerfile Normal file
View File

@@ -0,0 +1,13 @@
# 基础镜像
FROM redis
# author
MAINTAINER ruoyi
# 挂载目录
VOLUME /home/ruoyi/redis
# 创建目录
RUN mkdir -p /home/ruoyi/redis
# 指定路径
WORKDIR /home/ruoyi/redis
# 复制conf文件到路径
COPY ./conf/redis.conf /home/ruoyi/redis/redis.conf

View File

@@ -0,0 +1,15 @@
# 基础镜像
FROM openjdk:8-jre
# author
MAINTAINER ruoyi
# 挂载目录
VOLUME /home/ruoyi
# 创建目录
RUN mkdir -p /home/ruoyi
# 指定路径
WORKDIR /home/ruoyi
# 复制jar文件到路径
COPY ./jar/ruoyi-auth.jar /home/ruoyi/ruoyi-auth.jar
# 启动认证服务
ENTRYPOINT ["java","-jar","ruoyi-auth.jar"]

View File

@@ -0,0 +1 @@
存放认证中心打包好的jar文件用于docker启动应用。

View File

@@ -0,0 +1,15 @@
# 基础镜像
FROM openjdk:8-jre
# author
MAINTAINER ruoyi
# 挂载目录
VOLUME /home/ruoyi
# 创建目录
RUN mkdir -p /home/ruoyi
# 指定路径
WORKDIR /home/ruoyi
# 复制jar文件到路径
COPY ./jar/ruoyi-gateway.jar /home/ruoyi/ruoyi-gateway.jar
# 启动网关服务
ENTRYPOINT ["java","-jar","ruoyi-gateway.jar"]

View File

@@ -0,0 +1 @@
存放网关模块打包好的jar文件用于docker启动应用。

View File

@@ -0,0 +1,15 @@
# 基础镜像
FROM openjdk:8-jre
# author
MAINTAINER ruoyi
# 挂载目录
VOLUME /home/ruoyi
# 创建目录
RUN mkdir -p /home/ruoyi
# 指定路径
WORKDIR /home/ruoyi
# 复制jar文件到路径
COPY ./jar/ruoyi-modules-file.jar /home/ruoyi/ruoyi-modules-file.jar
# 启动文件服务
ENTRYPOINT ["java","-jar","ruoyi-modules-file.jar"]

View File

@@ -0,0 +1 @@
存放文件服务打包好的jar文件用于docker启动应用。

View File

@@ -0,0 +1,15 @@
# 基础镜像
FROM openjdk:8-jre
# author
MAINTAINER ruoyi
# 挂载目录
VOLUME /home/ruoyi
# 创建目录
RUN mkdir -p /home/ruoyi
# 指定路径
WORKDIR /home/ruoyi
# 复制jar文件到路径
COPY ./jar/ruoyi-modules-gen.jar /home/ruoyi/ruoyi-modules-gen.jar
# 启动代码生成服务
ENTRYPOINT ["java","-jar","ruoyi-modules-gen.jar"]

View File

@@ -0,0 +1 @@
存放代码生成打包好的jar文件用于docker启动应用。

View File

@@ -0,0 +1,15 @@
# 基础镜像
FROM openjdk:8-jre
# author
MAINTAINER ruoyi
# 挂载目录
VOLUME /home/ruoyi
# 创建目录
RUN mkdir -p /home/ruoyi
# 指定路径
WORKDIR /home/ruoyi
# 复制jar文件到路径
COPY ./jar/ruoyi-modules-job.jar /home/ruoyi/ruoyi-modules-job.jar
# 启动定时任务服务
ENTRYPOINT ["java","-jar","ruoyi-modules-job.jar"]

View File

@@ -0,0 +1 @@
存放定时任务打包好的jar文件用于docker启动应用。

View File

@@ -0,0 +1,15 @@
# 基础镜像
FROM openjdk:8-jre
# author
MAINTAINER ruoyi
# 挂载目录
VOLUME /home/ruoyi
# 创建目录
RUN mkdir -p /home/ruoyi
# 指定路径
WORKDIR /home/ruoyi
# 复制jar文件到路径
COPY ./jar/ruoyi-modules-system.jar /home/ruoyi/ruoyi-modules-system.jar
# 启动系统服务
ENTRYPOINT ["java","-jar","ruoyi-modules-system.jar"]

View File

@@ -0,0 +1 @@
存放系统模块打包好的jar文件用于docker启动应用。

View File

@@ -0,0 +1,15 @@
# 基础镜像
FROM openjdk:8-jre
# author
MAINTAINER ruoyi
# 挂载目录
VOLUME /home/ruoyi
# 创建目录
RUN mkdir -p /home/ruoyi
# 指定路径
WORKDIR /home/ruoyi
# 复制jar文件到路径
COPY ./jar/ruoyi-visual-monitor.jar /home/ruoyi/ruoyi-visual-monitor.jar
# 启动系统服务
ENTRYPOINT ["java","-jar","ruoyi-visual-monitor.jar"]

View File

@@ -0,0 +1 @@
存放监控中心打包好的jar文件用于docker启动应用。

135
pom.xml
View File

@@ -6,32 +6,40 @@
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>2.1.0</version> <version>3.3.0</version>
<name>ruoyi</name> <name>ruoyi</name>
<url>http://www.ruoyi.vip</url> <url>http://www.ruoyi.vip</url>
<description>若依微服务系统</description> <description>若依微服务系统</description>
<properties> <properties>
<ruoyi.version>2.1.0</ruoyi.version> <ruoyi.version>3.3.0</ruoyi.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version> <java.version>1.8</java.version>
<spring-boot.version>2.2.6.RELEASE</spring-boot.version> <spring-boot.version>2.5.6</spring-boot.version>
<spring-cloud.version>Hoxton.SR4</spring-cloud.version> <spring-cloud.version>2020.0.4</spring-cloud.version>
<spring-boot-admin.version>2.2.3</spring-boot-admin.version> <spring-cloud-alibaba.version>2021.1</spring-cloud-alibaba.version>
<spring-boot.mybatis>2.1.2</spring-boot.mybatis> <alibaba.nacos.version>2.0.3</alibaba.nacos.version>
<nacos.version>1.3.0</nacos.version> <spring-boot-admin.version>2.5.4</spring-boot-admin.version>
<swagger.fox.version>2.9.2</swagger.fox.version> <spring-boot.mybatis>2.2.0</spring-boot.mybatis>
<swagger.core.version>1.5.24</swagger.core.version> <swagger.fox.version>3.0.0</swagger.fox.version>
<swagger.core.version>1.6.2</swagger.core.version>
<tobato.version>1.27.2</tobato.version>
<kaptcha.version>2.3.2</kaptcha.version> <kaptcha.version>2.3.2</kaptcha.version>
<pagehelper.boot.version>1.2.12</pagehelper.boot.version> <pagehelper.boot.version>1.4.0</pagehelper.boot.version>
<commons.io.version>2.5</commons.io.version> <druid.version>1.2.8</druid.version>
<commons.fileupload.version>1.3.3</commons.fileupload.version> <dynamic-ds.version>3.5.0</dynamic-ds.version>
<velocity.version>1.7</velocity.version> <commons.io.version>2.11.0</commons.io.version>
<fastjson.version>1.2.70</fastjson.version> <commons.fileupload.version>1.4</commons.fileupload.version>
<poi.version>3.17</poi.version> <velocity.version>2.3</velocity.version>
<common-pool.version>2.6.2</common-pool.version> <fastjson.version>1.2.78</fastjson.version>
<jjwt.version>0.9.1</jjwt.version>
<minio.version>8.2.2</minio.version>
<poi.version>4.1.2</poi.version>
<common-pool.version>2.10.0</common-pool.version>
<commons-collections.version>3.2.2</commons-collections.version>
<transmittable-thread-local.version>2.12.2</transmittable-thread-local.version>
</properties> </properties>
<!-- 依赖声明 --> <!-- 依赖声明 -->
@@ -47,21 +55,21 @@
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>
<!-- SpringCloud Alibaba 微服务 --> <!-- SpringCloud Alibaba 微服务 -->
<dependency> <dependency>
<groupId>com.alibaba.cloud</groupId> <groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId> <artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.1.RELEASE</version> <version>${spring-cloud-alibaba.version}</version>
<type>pom</type> <type>pom</type>
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>
<!-- Alibaba Nacos 配置 --> <!-- Alibaba Nacos 配置 -->
<dependency> <dependency>
<groupId>com.alibaba.nacos</groupId> <groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-client</artifactId> <artifactId>nacos-client</artifactId>
<version>${nacos.version}</version> <version>${alibaba.nacos.version}</version>
</dependency> </dependency>
<!-- SpringBoot 依赖配置 --> <!-- SpringBoot 依赖配置 -->
<dependency> <dependency>
@@ -71,21 +79,28 @@
<type>pom</type> <type>pom</type>
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>
<!-- SpringBoot 监控客户端 --> <!-- SpringBoot 监控客户端 -->
<dependency> <dependency>
<groupId>de.codecentric</groupId> <groupId>de.codecentric</groupId>
<artifactId>spring-boot-admin-starter-client</artifactId> <artifactId>spring-boot-admin-starter-client</artifactId>
<version>${spring-boot-admin.version}</version> <version>${spring-boot-admin.version}</version>
</dependency> </dependency>
<!-- FastDFS 分布式文件系统 -->
<dependency>
<groupId>com.github.tobato</groupId>
<artifactId>fastdfs-client</artifactId>
<version>${tobato.version}</version>
</dependency>
<!-- Mybatis 依赖配置 --> <!-- Mybatis 依赖配置 -->
<dependency> <dependency>
<groupId>org.mybatis.spring.boot</groupId> <groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId> <artifactId>mybatis-spring-boot-starter</artifactId>
<version>${spring-boot.mybatis}</version> <version>${spring-boot.mybatis}</version>
</dependency> </dependency>
<!-- Swagger 依赖配置 --> <!-- Swagger 依赖配置 -->
<dependency> <dependency>
<groupId>io.swagger</groupId> <groupId>io.swagger</groupId>
@@ -136,17 +151,38 @@
<!-- 代码生成使用模板 --> <!-- 代码生成使用模板 -->
<dependency> <dependency>
<groupId>org.apache.velocity</groupId> <groupId>org.apache.velocity</groupId>
<artifactId>velocity</artifactId> <artifactId>velocity-engine-core</artifactId>
<version>${velocity.version}</version> <version>${velocity.version}</version>
</dependency> </dependency>
<!-- Collection 增强Java集合框架 -->
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>${commons-collections.version}</version>
</dependency>
<!-- JSON 解析器和生成器 --> <!-- JSON 解析器和生成器 -->
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId> <artifactId>fastjson</artifactId>
<version>${fastjson.version}</version> <version>${fastjson.version}</version>
</dependency> </dependency>
<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jjwt.version}</version>
</dependency>
<!-- 线程传递值 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
<version>${transmittable-thread-local.version}</version>
</dependency>
<!-- 公共资源池 --> <!-- 公共资源池 -->
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
@@ -155,69 +191,80 @@
</dependency> </dependency>
<!-- 核心模块 --> <!-- 核心模块 -->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-core</artifactId> <artifactId>ruoyi-common-core</artifactId>
<version>${ruoyi.version}</version> <version>${ruoyi.version}</version>
</dependency> </dependency>
<!-- 接口模块 --> <!-- 接口模块 -->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-swagger</artifactId> <artifactId>ruoyi-common-swagger</artifactId>
<version>${ruoyi.version}</version> <version>${ruoyi.version}</version>
</dependency> </dependency>
<!-- 安全模块 --> <!-- 安全模块 -->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-security</artifactId> <artifactId>ruoyi-common-security</artifactId>
<version>${ruoyi.version}</version> <version>${ruoyi.version}</version>
</dependency> </dependency>
<!-- 权限范围 --> <!-- 权限范围 -->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-datascope</artifactId> <artifactId>ruoyi-common-datascope</artifactId>
<version>${ruoyi.version}</version> <version>${ruoyi.version}</version>
</dependency> </dependency>
<!-- 多数据源 -->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-datasource</artifactId>
<version>${ruoyi.version}</version>
</dependency>
<!-- 日志记录 --> <!-- 日志记录 -->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-log</artifactId> <artifactId>ruoyi-common-log</artifactId>
<version>${ruoyi.version}</version> <version>${ruoyi.version}</version>
</dependency> </dependency>
<!-- 缓存服务 --> <!-- 缓存服务 -->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-redis</artifactId> <artifactId>ruoyi-common-redis</artifactId>
<version>${ruoyi.version}</version> <version>${ruoyi.version}</version>
</dependency> </dependency>
<!-- 系统接口 --> <!-- 系统接口 -->
<dependency> <dependency>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-api-system</artifactId> <artifactId>ruoyi-api-system</artifactId>
<version>${ruoyi.version}</version> <version>${ruoyi.version}</version>
</dependency> </dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>
<modules> <modules>
<module>ruoyi-auth</module> <module>ruoyi-auth</module>
<module>ruoyi-gateway</module> <module>ruoyi-gateway</module>
<module>ruoyi-visual</module> <module>ruoyi-visual</module>
<module>ruoyi-modules</module> <module>ruoyi-modules</module>
<module>ruoyi-api</module> <module>ruoyi-api</module>
<module>ruoyi-common</module> <module>ruoyi-common</module>
</modules> </modules>
<packaging>pom</packaging> <packaging>pom</packaging>
<dependencies> <dependencies>
<!-- bootstrap 启动器 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>2.1.0</version> <version>3.3.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-api</artifactId> <artifactId>ruoyi-api</artifactId>
<version>2.1.0</version> <version>3.3.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@@ -0,0 +1,29 @@
package com.ruoyi.system.api;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.constant.ServiceNameConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.api.domain.SysFile;
import com.ruoyi.system.api.factory.RemoteFileFallbackFactory;
/**
* 文件服务
*
* @author ruoyi
*/
@FeignClient(contextId = "remoteFileService", value = ServiceNameConstants.FILE_SERVICE, fallbackFactory = RemoteFileFallbackFactory.class)
public interface RemoteFileService
{
/**
* 上传文件
*
* @param file 文件信息
* @return 结果
*/
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public R<SysFile> upload(@RequestPart(value = "file") MultipartFile file);
}

View File

@@ -3,9 +3,11 @@ package com.ruoyi.system.api;
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestHeader;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.constant.ServiceNameConstants; import com.ruoyi.common.core.constant.ServiceNameConstants;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.api.domain.SysLogininfor;
import com.ruoyi.system.api.domain.SysOperLog; import com.ruoyi.system.api.domain.SysOperLog;
import com.ruoyi.system.api.factory.RemoteLogFallbackFactory; import com.ruoyi.system.api.factory.RemoteLogFallbackFactory;
@@ -21,20 +23,19 @@ public interface RemoteLogService
* 保存系统日志 * 保存系统日志
* *
* @param sysOperLog 日志实体 * @param sysOperLog 日志实体
* @param source 请求来源
* @return 结果 * @return 结果
*/ */
@PostMapping("/operlog") @PostMapping("/operlog")
R<Boolean> saveLog(@RequestBody SysOperLog sysOperLog); public R<Boolean> saveLog(@RequestBody SysOperLog sysOperLog, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/** /**
* 保存访问记录 * 保存访问记录
* *
* @param username 用户名称 * @param sysLogininfor 访问实体
* @param status 状态 * @param source 请求来源
* @param message 消息
* @return 结果 * @return 结果
*/ */
@PostMapping("/logininfor") @PostMapping("/logininfor")
R<Boolean> saveLogininfor(@RequestParam("username") String username, @RequestParam("status") String status, public R<Boolean> saveLogininfor(@RequestBody SysLogininfor sysLogininfor, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
@RequestParam("message") String message);
} }

View File

@@ -3,10 +3,15 @@ package com.ruoyi.system.api;
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.constant.ServiceNameConstants; import com.ruoyi.common.core.constant.ServiceNameConstants;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.factory.RemoteUserFallbackFactory; import com.ruoyi.system.api.factory.RemoteUserFallbackFactory;
import com.ruoyi.system.api.model.UserInfo; import com.ruoyi.system.api.model.LoginUser;
/** /**
* 用户服务 * 用户服务
@@ -20,8 +25,19 @@ public interface RemoteUserService
* 通过用户名查询用户信息 * 通过用户名查询用户信息
* *
* @param username 用户名 * @param username 用户名
* @param source 请求来源
* @return 结果 * @return 结果
*/ */
@GetMapping(value = "/user/info/{username}") @GetMapping("/user/info/{username}")
public R<UserInfo> getUserInfo(@PathVariable("username") String username); public R<LoginUser> getUserInfo(@PathVariable("username") String username, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
/**
* 注册用户信息
*
* @param sysUser 用户信息
* @param source 请求来源
* @return 结果
*/
@PostMapping("/user/register")
public R<Boolean> registerUserInfo(@RequestBody SysUser sysUser, @RequestHeader(SecurityConstants.FROM_SOURCE) String source);
} }

View File

@@ -1,4 +1,4 @@
package com.ruoyi.system.domain; package com.ruoyi.system.api.domain;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;

View File

@@ -1,4 +1,4 @@
package com.ruoyi.system.domain; package com.ruoyi.system.api.domain;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size; import javax.validation.constraints.Size;

View File

@@ -0,0 +1,50 @@
package com.ruoyi.system.api.domain;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
/**
* 文件信息
*
* @author ruoyi
*/
public class SysFile
{
/**
* 文件名称
*/
private String name;
/**
* 文件地址
*/
private String url;
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getUrl()
{
return url;
}
public void setUrl(String url)
{
this.url = url;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("name", getName())
.append("url", getUrl())
.toString();
}
}

View File

@@ -1,4 +1,4 @@
package com.ruoyi.system.domain; package com.ruoyi.system.api.domain;
import java.util.Date; import java.util.Date;
import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonFormat;

View File

@@ -33,10 +33,16 @@ public class SysRole extends BaseEntity
@Excel(name = "角色排序") @Excel(name = "角色排序")
private String roleSort; private String roleSort;
/** 数据范围1所有数据权限2自定义数据权限3本部门数据权限4本部门及以下数据权限 */ /** 数据范围1所有数据权限2自定义数据权限3本部门数据权限4本部门及以下数据权限5仅本人数据权限 */
@Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限") @Excel(name = "数据范围", readConverterExp = "1=所有数据权限,2=自定义数据权限,3=本部门数据权限,4=本部门及以下数据权限,5=仅本人数据权限")
private String dataScope; private String dataScope;
/** 菜单树选择项是否关联显示( 0父子不互相关联显示 1父子互相关联显示 */
private boolean menuCheckStrictly;
/** 部门树选择项是否关联显示0父子不互相关联显示 1父子互相关联显示 */
private boolean deptCheckStrictly;
/** 角色状态0正常 1停用 */ /** 角色状态0正常 1停用 */
@Excel(name = "角色状态", readConverterExp = "0=正常,1=停用") @Excel(name = "角色状态", readConverterExp = "0=正常,1=停用")
private String status; private String status;
@@ -128,6 +134,26 @@ public class SysRole extends BaseEntity
this.dataScope = dataScope; this.dataScope = dataScope;
} }
public boolean isMenuCheckStrictly()
{
return menuCheckStrictly;
}
public void setMenuCheckStrictly(boolean menuCheckStrictly)
{
this.menuCheckStrictly = menuCheckStrictly;
}
public boolean isDeptCheckStrictly()
{
return deptCheckStrictly;
}
public void setDeptCheckStrictly(boolean deptCheckStrictly)
{
this.deptCheckStrictly = deptCheckStrictly;
}
public String getStatus() public String getStatus()
{ {
return status; return status;
@@ -177,7 +203,8 @@ public class SysRole extends BaseEntity
{ {
this.deptIds = deptIds; this.deptIds = deptIds;
} }
@Override
public String toString() { public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("roleId", getRoleId()) .append("roleId", getRoleId())
@@ -185,6 +212,8 @@ public class SysRole extends BaseEntity
.append("roleKey", getRoleKey()) .append("roleKey", getRoleKey())
.append("roleSort", getRoleSort()) .append("roleSort", getRoleSort())
.append("dataScope", getDataScope()) .append("dataScope", getDataScope())
.append("menuCheckStrictly", isMenuCheckStrictly())
.append("deptCheckStrictly", isDeptCheckStrictly())
.append("status", getStatus()) .append("status", getStatus())
.append("delFlag", getDelFlag()) .append("delFlag", getDelFlag())
.append("createBy", getCreateBy()) .append("createBy", getCreateBy())

View File

@@ -57,9 +57,6 @@ public class SysUser extends BaseEntity
/** 密码 */ /** 密码 */
private String password; private String password;
/** 盐加密 */
private String salt;
/** 帐号状态0正常 1停用 */ /** 帐号状态0正常 1停用 */
@Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用") @Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用")
private String status; private String status;
@@ -67,12 +64,12 @@ public class SysUser extends BaseEntity
/** 删除标志0代表存在 2代表删除 */ /** 删除标志0代表存在 2代表删除 */
private String delFlag; private String delFlag;
/** 最后登IP */ /** 最后登IP */
@Excel(name = "最后登IP", type = Type.EXPORT) @Excel(name = "最后登IP", type = Type.EXPORT)
private String loginIp; private String loginIp;
/** 最后登时间 */ /** 最后登时间 */
@Excel(name = "最后登时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT) @Excel(name = "最后登时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
private Date loginDate; private Date loginDate;
/** 部门对象 */ /** 部门对象 */
@@ -91,6 +88,9 @@ public class SysUser extends BaseEntity
/** 岗位组 */ /** 岗位组 */
private Long[] postIds; private Long[] postIds;
/** 角色ID */
private Long roleId;
public SysUser() public SysUser()
{ {
@@ -208,16 +208,6 @@ public class SysUser extends BaseEntity
this.password = password; this.password = password;
} }
public String getSalt()
{
return salt;
}
public void setSalt(String salt)
{
this.salt = salt;
}
public String getStatus() public String getStatus()
{ {
return status; return status;
@@ -297,7 +287,16 @@ public class SysUser extends BaseEntity
{ {
this.postIds = postIds; this.postIds = postIds;
} }
public Long getRoleId()
{
return roleId;
}
public void setRoleId(Long roleId)
{
this.roleId = roleId;
}
@Override @Override
public String toString() { public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
@@ -310,7 +309,6 @@ public class SysUser extends BaseEntity
.append("sex", getSex()) .append("sex", getSex())
.append("avatar", getAvatar()) .append("avatar", getAvatar())
.append("password", getPassword()) .append("password", getPassword())
.append("salt", getSalt())
.append("status", getStatus()) .append("status", getStatus())
.append("delFlag", getDelFlag()) .append("delFlag", getDelFlag())
.append("loginIp", getLoginIp()) .append("loginIp", getLoginIp())

View File

@@ -0,0 +1,35 @@
package com.ruoyi.system.api.factory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.api.RemoteFileService;
import com.ruoyi.system.api.domain.SysFile;
/**
* 文件服务降级处理
*
* @author ruoyi
*/
@Component
public class RemoteFileFallbackFactory implements FallbackFactory<RemoteFileService>
{
private static final Logger log = LoggerFactory.getLogger(RemoteFileFallbackFactory.class);
@Override
public RemoteFileService create(Throwable throwable)
{
log.error("文件服务调用失败:{}", throwable.getMessage());
return new RemoteFileService()
{
@Override
public R<SysFile> upload(MultipartFile file)
{
return R.fail("上传文件失败:" + throwable.getMessage());
}
};
}
}

View File

@@ -2,11 +2,12 @@ package com.ruoyi.system.api.factory;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.api.RemoteLogService; import com.ruoyi.system.api.RemoteLogService;
import com.ruoyi.system.api.domain.SysLogininfor;
import com.ruoyi.system.api.domain.SysOperLog; import com.ruoyi.system.api.domain.SysOperLog;
import feign.hystrix.FallbackFactory;
/** /**
* 日志服务降级处理 * 日志服务降级处理
@@ -25,13 +26,13 @@ public class RemoteLogFallbackFactory implements FallbackFactory<RemoteLogServic
return new RemoteLogService() return new RemoteLogService()
{ {
@Override @Override
public R<Boolean> saveLog(SysOperLog sysOperLog) public R<Boolean> saveLog(SysOperLog sysOperLog, String source)
{ {
return null; return null;
} }
@Override @Override
public R<Boolean> saveLogininfor(String username, String status, String message) public R<Boolean> saveLogininfor(SysLogininfor sysLogininfor, String source)
{ {
return null; return null;
} }

View File

@@ -2,11 +2,12 @@ package com.ruoyi.system.api.factory;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.api.RemoteUserService; import com.ruoyi.system.api.RemoteUserService;
import com.ruoyi.system.api.model.UserInfo; import com.ruoyi.system.api.domain.SysUser;
import feign.hystrix.FallbackFactory; import com.ruoyi.system.api.model.LoginUser;
/** /**
* 用户服务降级处理 * 用户服务降级处理
@@ -25,9 +26,15 @@ public class RemoteUserFallbackFactory implements FallbackFactory<RemoteUserServ
return new RemoteUserService() return new RemoteUserService()
{ {
@Override @Override
public R<UserInfo> getUserInfo(String username) public R<LoginUser> getUserInfo(String username, String source)
{ {
return null; return R.fail("获取用户失败:" + throwable.getMessage());
}
@Override
public R<Boolean> registerUserInfo(SysUser sysUser, String source)
{
return R.fail("注册用户失败:" + throwable.getMessage());
} }
}; };
} }

View File

@@ -0,0 +1,150 @@
package com.ruoyi.system.api.model;
import java.io.Serializable;
import java.util.Set;
import com.ruoyi.system.api.domain.SysUser;
/**
* 用户信息
*
* @author ruoyi
*/
public class LoginUser implements Serializable
{
private static final long serialVersionUID = 1L;
/**
* 用户唯一标识
*/
private String token;
/**
* 用户名id
*/
private Long userid;
/**
* 用户名
*/
private String username;
/**
* 登录时间
*/
private Long loginTime;
/**
* 过期时间
*/
private Long expireTime;
/**
* 登录IP地址
*/
private String ipaddr;
/**
* 权限列表
*/
private Set<String> permissions;
/**
* 角色列表
*/
private Set<String> roles;
/**
* 用户信息
*/
private SysUser sysUser;
public String getToken()
{
return token;
}
public void setToken(String token)
{
this.token = token;
}
public Long getUserid()
{
return userid;
}
public void setUserid(Long userid)
{
this.userid = userid;
}
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public Long getLoginTime()
{
return loginTime;
}
public void setLoginTime(Long loginTime)
{
this.loginTime = loginTime;
}
public Long getExpireTime()
{
return expireTime;
}
public void setExpireTime(Long expireTime)
{
this.expireTime = expireTime;
}
public String getIpaddr()
{
return ipaddr;
}
public void setIpaddr(String ipaddr)
{
this.ipaddr = ipaddr;
}
public Set<String> getPermissions()
{
return permissions;
}
public void setPermissions(Set<String> permissions)
{
this.permissions = permissions;
}
public Set<String> getRoles()
{
return roles;
}
public void setRoles(Set<String> roles)
{
this.roles = roles;
}
public SysUser getSysUser()
{
return sysUser;
}
public void setSysUser(SysUser sysUser)
{
this.sysUser = sysUser;
}
}

View File

@@ -1,60 +0,0 @@
package com.ruoyi.system.api.model;
import java.io.Serializable;
import java.util.Set;
import com.ruoyi.system.api.domain.SysUser;
/**
* 用户信息
*
* @author ruoyi
*/
public class UserInfo implements Serializable
{
private static final long serialVersionUID = 1L;
/**
* 用户基本信息
*/
private SysUser sysUser;
/**
* 权限标识集合
*/
private Set<String> permissions;
/**
* 角色集合
*/
private Set<String> roles;
public SysUser getSysUser()
{
return sysUser;
}
public void setSysUser(SysUser sysUser)
{
this.sysUser = sysUser;
}
public Set<String> getPermissions()
{
return permissions;
}
public void setPermissions(Set<String> permissions)
{
this.permissions = permissions;
}
public Set<String> getRoles()
{
return roles;
}
public void setRoles(Set<String> roles)
{
this.roles = roles;
}
}

View File

@@ -1,3 +1,4 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.ruoyi.system.api.factory.RemoteUserFallbackFactory,\ com.ruoyi.system.api.factory.RemoteUserFallbackFactory,\
com.ruoyi.system.api.factory.RemoteLogFallbackFactory com.ruoyi.system.api.factory.RemoteLogFallbackFactory, \
com.ruoyi.system.api.factory.RemoteFileFallbackFactory

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>2.1.0</version> <version>3.3.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -16,22 +16,22 @@
<dependencies> <dependencies>
<!-- SpringCloud Ailibaba Nacos --> <!-- SpringCloud Alibaba Nacos -->
<dependency> <dependency>
<groupId>com.alibaba.cloud</groupId> <groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency> </dependency>
<!-- SpringCloud Ailibaba Nacos Config --> <!-- SpringCloud Alibaba Nacos Config -->
<dependency> <dependency>
<groupId>com.alibaba.cloud</groupId> <groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency> </dependency>
<!-- SpringCloud Netflix Hystrix --> <!-- SpringCloud Alibaba Sentinel -->
<dependency> <dependency>
<groupId>org.springframework.cloud</groupId> <groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency> </dependency>
<!-- SpringBoot Web --> <!-- SpringBoot Web -->
@@ -40,10 +40,10 @@
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> </dependency>
<!-- Mysql Connector --> <!-- SpringBoot Actuator -->
<dependency> <dependency>
<groupId>mysql</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>mysql-connector-java</artifactId> <artifactId>spring-boot-starter-actuator</artifactId>
</dependency> </dependency>
<!-- RuoYi Common Security--> <!-- RuoYi Common Security-->
@@ -52,15 +52,10 @@
<artifactId>ruoyi-common-security</artifactId> <artifactId>ruoyi-common-security</artifactId>
</dependency> </dependency>
<!-- RuoYi Common Redis-->
<dependency>
<groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common-redis</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
<finalName>${project.artifactId}</finalName>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>

View File

@@ -1,7 +1,8 @@
package com.ruoyi.auth; package com.ruoyi.auth;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.cloud.client.SpringCloudApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import com.ruoyi.common.security.annotation.EnableRyFeignClients; import com.ruoyi.common.security.annotation.EnableRyFeignClients;
/** /**
@@ -10,7 +11,7 @@ import com.ruoyi.common.security.annotation.EnableRyFeignClients;
* @author ruoyi * @author ruoyi
*/ */
@EnableRyFeignClients @EnableRyFeignClients
@SpringCloudApplication @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class })
public class RuoYiAuthApplication public class RuoYiAuthApplication
{ {
public static void main(String[] args) public static void main(String[] args)

View File

@@ -1,131 +0,0 @@
package com.ruoyi.auth.config;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;
import com.ruoyi.auth.exception.CustomWebResponseExceptionTranslator;
import com.ruoyi.common.core.constant.CacheConstants;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.security.domain.LoginUser;
import com.ruoyi.common.security.service.RedisClientDetailsService;
/**
* OAuth2 认证服务配置
*
* @author ruoyi
*/
@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter
{
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private DataSource dataSource;
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private TokenEnhancer tokenEnhancer;
/**
* 定义授权和令牌端点以及令牌服务
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
{
endpoints
// 请求方式
.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST)
// 指定token存储位置
.tokenStore(tokenStore())
// 自定义生成令牌
.tokenEnhancer(tokenEnhancer)
// 用户账号密码认证
.userDetailsService(userDetailsService)
// 指定认证管理器
.authenticationManager(authenticationManager)
// 是否重复使用 refresh_token
.reuseRefreshTokens(false)
// 自定义异常处理
.exceptionTranslator(new CustomWebResponseExceptionTranslator());
}
/**
* 配置令牌端点(Token Endpoint)的安全约束
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer)
{
oauthServer.allowFormAuthenticationForClients().checkTokenAccess("permitAll()");
}
/**
* 声明 ClientDetails实现
*/
public RedisClientDetailsService clientDetailsService()
{
RedisClientDetailsService clientDetailsService = new RedisClientDetailsService(dataSource);
return clientDetailsService;
}
/**
* 配置客户端详情
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception
{
clients.withClientDetails(clientDetailsService());
}
/**
* 基于 Redis 实现,令牌保存到缓存
*/
@Bean
public TokenStore tokenStore()
{
RedisTokenStore tokenStore = new RedisTokenStore(redisConnectionFactory);
tokenStore.setPrefix(CacheConstants.OAUTH_ACCESS);
return tokenStore;
}
/**
* 自定义生成令牌
*/
@Bean
public TokenEnhancer tokenEnhancer()
{
return (accessToken, authentication) -> {
if (authentication.getUserAuthentication() != null)
{
Map<String, Object> additionalInformation = new LinkedHashMap<String, Object>();
LoginUser user = (LoginUser) authentication.getUserAuthentication().getPrincipal();
additionalInformation.put(SecurityConstants.DETAILS_USER_ID, user.getUserId());
additionalInformation.put(SecurityConstants.DETAILS_USERNAME, user.getUsername());
((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInformation);
}
return accessToken;
};
}
}

View File

@@ -1,59 +0,0 @@
package com.ruoyi.auth.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* Security 安全认证相关配置
* Oauth2依赖于Security 默认情况下WebSecurityConfig执行比ResourceServerConfig优先
*
* @author ruoyi
*/
@Order(99)
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
{
@Autowired
private UserDetailsService userDetailsService;
@Bean
public PasswordEncoder passwordEncoder()
{
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception
{
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception
{
http
.authorizeRequests()
.antMatchers(
"/actuator/**",
"/oauth/*",
"/token/**").permitAll()
.anyRequest().authenticated()
.and().csrf().disable();
}
}

View File

@@ -1,20 +1,21 @@
package com.ruoyi.auth.controller; package com.ruoyi.auth.controller;
import java.util.Map; import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.RequestHeader; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import com.ruoyi.common.core.constant.Constants; import com.ruoyi.auth.form.LoginBody;
import com.ruoyi.common.core.constant.SecurityConstants; import com.ruoyi.auth.form.RegisterBody;
import com.ruoyi.auth.service.SysLoginService;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.utils.JwtUtils;
import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.system.api.RemoteLogService; import com.ruoyi.common.security.auth.AuthUtil;
import com.ruoyi.common.security.service.TokenService;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.system.api.model.LoginUser;
/** /**
* token 控制 * token 控制
@@ -22,43 +23,56 @@ import com.ruoyi.system.api.RemoteLogService;
* @author ruoyi * @author ruoyi
*/ */
@RestController @RestController
@RequestMapping("/token")
public class TokenController public class TokenController
{ {
@Autowired @Autowired
private TokenStore tokenStore; private TokenService tokenService;
@Autowired @Autowired
private RemoteLogService remoteLogService; private SysLoginService sysLoginService;
@DeleteMapping("/logout") @PostMapping("login")
public R<?> logout(@RequestHeader(value = HttpHeaders.AUTHORIZATION, required = false) String authHeader) public R<?> login(@RequestBody LoginBody form)
{ {
if (StringUtils.isEmpty(authHeader)) // 用户登录
{ LoginUser userInfo = sysLoginService.login(form.getUsername(), form.getPassword());
return R.ok(); // 获取登录token
} return R.ok(tokenService.createToken(userInfo));
}
String tokenValue = authHeader.replace(OAuth2AccessToken.BEARER_TYPE, StringUtils.EMPTY).trim(); @DeleteMapping("logout")
OAuth2AccessToken accessToken = tokenStore.readAccessToken(tokenValue); public R<?> logout(HttpServletRequest request)
if (accessToken == null || StringUtils.isEmpty(accessToken.getValue())) {
String token = SecurityUtils.getToken(request);
if (StringUtils.isNotEmpty(token))
{ {
return R.ok(); String username = JwtUtils.getUserName(token);
} // 删除用户缓存记录
AuthUtil.logoutByToken(token);
// 清空 access token
tokenStore.removeAccessToken(accessToken);
// 清空 refresh token
OAuth2RefreshToken refreshToken = accessToken.getRefreshToken();
tokenStore.removeRefreshToken(refreshToken);
Map<String, ?> map = accessToken.getAdditionalInformation();
if (map.containsKey(SecurityConstants.DETAILS_USERNAME))
{
String username = (String) map.get(SecurityConstants.DETAILS_USERNAME);
// 记录用户退出日志 // 记录用户退出日志
remoteLogService.saveLogininfor(username, Constants.LOGOUT, "退出成功"); sysLoginService.logout(username);
} }
return R.ok(); return R.ok();
} }
@PostMapping("refresh")
public R<?> refresh(HttpServletRequest request)
{
LoginUser loginUser = tokenService.getLoginUser(request);
if (StringUtils.isNotNull(loginUser))
{
// 刷新令牌有效期
tokenService.refreshToken(loginUser);
return R.ok();
}
return R.ok();
}
@PostMapping("register")
public R<?> register(@RequestBody RegisterBody registerBody)
{
// 用户注册
sysLoginService.register(registerBody.getUsername(), registerBody.getPassword());
return R.ok();
}
} }

View File

@@ -1,21 +0,0 @@
package com.ruoyi.auth.controller;
import java.security.Principal;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 身份信息获取
*
* @author ruoyi
*/
@RestController
@RequestMapping("/oauth")
public class UserController
{
@RequestMapping("/user")
public Principal user(Principal user)
{
return user;
}
}

View File

@@ -1,20 +0,0 @@
package com.ruoyi.auth.exception;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
/**
* oauth2自定义异常
*
* @author ruoyi
**/
@JsonSerialize(using = CustomOauthExceptionSerializer.class)
public class CustomOauthException extends OAuth2Exception
{
private static final long serialVersionUID = 1L;
public CustomOauthException(String msg)
{
super(msg);
}
}

View File

@@ -1,48 +0,0 @@
package com.ruoyi.auth.exception;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.ruoyi.common.core.constant.HttpStatus;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.domain.AjaxResult;
/**
* 自定义异常返回
*
* @author ruoyi
**/
public class CustomOauthExceptionSerializer extends StdSerializer<CustomOauthException>
{
private static final long serialVersionUID = 1L;
private static final Logger log = LoggerFactory.getLogger(CustomOauthExceptionSerializer.class);
public static final String BAD_CREDENTIALS = "Bad credentials";
public CustomOauthExceptionSerializer()
{
super(CustomOauthException.class);
}
@Override
public void serialize(CustomOauthException e, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
throws IOException
{
jsonGenerator.writeStartObject();
jsonGenerator.writeNumberField(AjaxResult.CODE_TAG, HttpStatus.ERROR);
if (StringUtils.equals(e.getMessage(), BAD_CREDENTIALS))
{
jsonGenerator.writeStringField(AjaxResult.MSG_TAG, "用户名或密码错误");
}
else
{
log.warn("oauth2 认证异常 {} ", e);
jsonGenerator.writeStringField(AjaxResult.MSG_TAG, e.getMessage());
}
jsonGenerator.writeEndObject();
}
}

View File

@@ -1,20 +0,0 @@
package com.ruoyi.auth.exception;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
/**
* OAuth2 自定义异常处理
*
* @author ruoyi
*/
public class CustomWebResponseExceptionTranslator implements WebResponseExceptionTranslator<OAuth2Exception>
{
@Override
public ResponseEntity<OAuth2Exception> translate(Exception e)
{
return ResponseEntity.status(HttpStatus.OK).body(new CustomOauthException(e.getMessage()));
}
}

View File

@@ -0,0 +1,39 @@
package com.ruoyi.auth.form;
/**
* 用户登录对象
*
* @author ruoyi
*/
public class LoginBody
{
/**
* 用户名
*/
private String username;
/**
* 用户密码
*/
private String password;
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
}

View File

@@ -0,0 +1,11 @@
package com.ruoyi.auth.form;
/**
* 用户注册对象
*
* @author ruoyi
*/
public class RegisterBody extends LoginBody
{
}

View File

@@ -1,39 +0,0 @@
package com.ruoyi.auth.handler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.security.authentication.event.AuthenticationSuccessEvent;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Component;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.security.domain.LoginUser;
import com.ruoyi.system.api.RemoteLogService;
/**
* 认证成功处理
*
* @author ruoyi
*/
@Component
public class AuthenticationSuccessEventHandler implements ApplicationListener<AuthenticationSuccessEvent>
{
@Autowired
private RemoteLogService remoteLogService;
@Override
public void onApplicationEvent(AuthenticationSuccessEvent event)
{
Authentication authentication = (Authentication) event.getSource();
if (StringUtils.isNotEmpty(authentication.getAuthorities())
&& authentication.getPrincipal() instanceof LoginUser)
{
LoginUser user = (LoginUser) authentication.getPrincipal();
String username = user.getUsername();
// 记录用户登录日志
remoteLogService.saveLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功");
}
}
}

View File

@@ -0,0 +1,159 @@
package com.ruoyi.auth.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.enums.UserStatus;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.ServletUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.utils.ip.IpUtils;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.system.api.RemoteLogService;
import com.ruoyi.system.api.RemoteUserService;
import com.ruoyi.system.api.domain.SysLogininfor;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.model.LoginUser;
/**
* 登录校验方法
*
* @author ruoyi
*/
@Component
public class SysLoginService
{
@Autowired
private RemoteLogService remoteLogService;
@Autowired
private RemoteUserService remoteUserService;
/**
* 登录
*/
public LoginUser login(String username, String password)
{
// 用户名或密码为空 错误
if (StringUtils.isAnyBlank(username, password))
{
recordLogininfor(username, Constants.LOGIN_FAIL, "用户/密码必须填写");
throw new ServiceException("用户/密码必须填写");
}
// 密码如果不在指定范围内 错误
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH)
{
recordLogininfor(username, Constants.LOGIN_FAIL, "用户密码不在指定范围");
throw new ServiceException("用户密码不在指定范围");
}
// 用户名不在指定范围内 错误
if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|| username.length() > UserConstants.USERNAME_MAX_LENGTH)
{
recordLogininfor(username, Constants.LOGIN_FAIL, "用户名不在指定范围");
throw new ServiceException("用户名不在指定范围");
}
// 查询用户信息
R<LoginUser> userResult = remoteUserService.getUserInfo(username, SecurityConstants.INNER);
if (R.FAIL == userResult.getCode())
{
throw new ServiceException(userResult.getMsg());
}
if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData()))
{
recordLogininfor(username, Constants.LOGIN_FAIL, "登录用户不存在");
throw new ServiceException("登录用户:" + username + " 不存在");
}
LoginUser userInfo = userResult.getData();
SysUser user = userResult.getData().getSysUser();
if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
{
recordLogininfor(username, Constants.LOGIN_FAIL, "对不起,您的账号已被删除");
throw new ServiceException("对不起,您的账号:" + username + " 已被删除");
}
if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
{
recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员");
throw new ServiceException("对不起,您的账号:" + username + " 已停用");
}
if (!SecurityUtils.matchesPassword(password, user.getPassword()))
{
recordLogininfor(username, Constants.LOGIN_FAIL, "用户密码错误");
throw new ServiceException("用户不存在/密码错误");
}
recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功");
return userInfo;
}
public void logout(String loginName)
{
recordLogininfor(loginName, Constants.LOGOUT, "退出成功");
}
/**
* 注册
*/
public void register(String username, String password)
{
// 用户名或密码为空 错误
if (StringUtils.isAnyBlank(username, password))
{
throw new ServiceException("用户/密码必须填写");
}
if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|| username.length() > UserConstants.USERNAME_MAX_LENGTH)
{
throw new ServiceException("账户长度必须在2到20个字符之间");
}
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH)
{
throw new ServiceException("密码长度必须在5到20个字符之间");
}
// 注册用户信息
SysUser sysUser = new SysUser();
sysUser.setUserName(username);
sysUser.setNickName(username);
sysUser.setPassword(SecurityUtils.encryptPassword(password));
R<?> registerResult = remoteUserService.registerUserInfo(sysUser, SecurityConstants.INNER);
if (R.FAIL == registerResult.getCode())
{
throw new ServiceException(registerResult.getMsg());
}
recordLogininfor(username, Constants.REGISTER, "注册成功");
}
/**
* 记录登录信息
*
* @param username 用户名
* @param status 状态
* @param message 消息内容
* @return
*/
public void recordLogininfor(String username, String status, String message)
{
SysLogininfor logininfor = new SysLogininfor();
logininfor.setUserName(username);
logininfor.setIpaddr(IpUtils.getIpAddr(ServletUtils.getRequest()));
logininfor.setMsg(message);
// 日志状态
if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER))
{
logininfor.setStatus("0");
}
else if (Constants.LOGIN_FAIL.equals(status))
{
logininfor.setStatus("1");
}
remoteLogService.saveLogininfor(logininfor, SecurityConstants.INNER);
}
}

View File

@@ -21,4 +21,5 @@ spring:
# 配置文件格式 # 配置文件格式
file-extension: yml file-extension: yml
# 共享配置 # 共享配置
shared-dataids: application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension} shared-configs:
- application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!-- 日志存放路径 -->
<property name="log.path" value="logs/ruoyi-auth" />
<!-- 日志输出格式 -->
<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<!-- 系统日志输出 -->
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/info.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>INFO</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/error.log</file>
<!-- 循环政策:基于时间创建日志文件 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 日志文件名格式 -->
<fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
<!-- 日志最大的历史 60天 -->
<maxHistory>60</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<!-- 过滤的级别 -->
<level>ERROR</level>
<!-- 匹配时的操作:接收(记录) -->
<onMatch>ACCEPT</onMatch>
<!-- 不匹配时的操作:拒绝(不记录) -->
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<!-- 系统模块日志级别控制 -->
<logger name="com.ruoyi" level="info" />
<!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" />
<root level="info">
<appender-ref ref="console" />
</root>
<!--系统操作日志-->
<root level="info">
<appender-ref ref="file_info" />
<appender-ref ref="file_error" />
</root>
</configuration>

View File

@@ -4,7 +4,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi</artifactId> <artifactId>ruoyi</artifactId>
<version>2.1.0</version> <version>3.3.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -15,6 +15,7 @@
<module>ruoyi-common-swagger</module> <module>ruoyi-common-swagger</module>
<module>ruoyi-common-security</module> <module>ruoyi-common-security</module>
<module>ruoyi-common-datascope</module> <module>ruoyi-common-datascope</module>
<module>ruoyi-common-datasource</module>
</modules> </modules>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>

View File

@@ -5,7 +5,7 @@
<parent> <parent>
<groupId>com.ruoyi</groupId> <groupId>com.ruoyi</groupId>
<artifactId>ruoyi-common</artifactId> <artifactId>ruoyi-common</artifactId>
<version>2.1.0</version> <version>3.3.0</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@@ -16,91 +16,115 @@
</description> </description>
<dependencies> <dependencies>
<!-- SpringCloud Openfeign --> <!-- SpringCloud Openfeign -->
<dependency> <dependency>
<groupId>org.springframework.cloud</groupId> <groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId> <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency> </dependency>
<!-- Spring Context Support --> <!-- SpringCloud Loadbalancer -->
<dependency> <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<!-- Spring Context Support -->
<dependency>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId> <artifactId>spring-context-support</artifactId>
</dependency> </dependency>
<!-- Spring Web --> <!-- Spring Web -->
<dependency> <dependency>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId> <artifactId>spring-web</artifactId>
</dependency> </dependency>
<!-- Transmittable ThreadLocal -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
</dependency>
<!-- Apache Commons Pool2 --> <!-- Apache Commons Pool2 -->
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId> <artifactId>commons-pool2</artifactId>
</dependency> </dependency>
<!-- Pagehelper --> <!-- Pagehelper -->
<dependency> <dependency>
<groupId>com.github.pagehelper</groupId> <groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId> <artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency> </dependency>
<!-- Java Validation --> <!-- Hibernate Validator -->
<dependency> <dependency>
<groupId>javax.validation</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>validation-api</artifactId> <artifactId>spring-boot-starter-validation</artifactId>
</dependency> </dependency>
<!-- Jackson --> <!-- Jackson -->
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId> <artifactId>jackson-databind</artifactId>
</dependency> </dependency>
<!-- Alibaba Fastjson --> <!-- Alibaba Fastjson -->
<dependency> <dependency>
<groupId>com.alibaba</groupId> <groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId> <artifactId>fastjson</artifactId>
</dependency> </dependency>
<!-- Jwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<!-- Jaxb -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<!-- Apache Lang3 --> <!-- Apache Lang3 -->
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>
</dependency> </dependency>
<!-- Commons Io --> <!-- Commons Io -->
<dependency> <dependency>
<groupId>commons-io</groupId> <groupId>commons-io</groupId>
<artifactId>commons-io</artifactId> <artifactId>commons-io</artifactId>
</dependency> </dependency>
<!-- Commons Fileupload --> <!-- Commons Fileupload -->
<dependency> <dependency>
<groupId>commons-fileupload</groupId> <groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId> <artifactId>commons-fileupload</artifactId>
</dependency> </dependency>
<!-- excel工具 --> <!-- excel工具 -->
<dependency> <dependency>
<groupId>org.apache.poi</groupId> <groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId> <artifactId>poi-ooxml</artifactId>
</dependency> </dependency>
<!-- Java Servlet --> <!-- Java Servlet -->
<dependency> <dependency>
<groupId>javax.servlet</groupId> <groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId> <artifactId>javax.servlet-api</artifactId>
</dependency> </dependency>
<!-- Swagger --> <!-- Swagger -->
<dependency> <dependency>
<groupId>io.swagger</groupId> <groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId> <artifactId>swagger-annotations</artifactId>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -4,6 +4,8 @@ import java.lang.annotation.ElementType;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import java.math.BigDecimal;
import com.ruoyi.common.core.utils.poi.ExcelHandlerAdapter;
/** /**
* 自定义导出Excel数据注解 * 自定义导出Excel数据注解
@@ -39,6 +41,16 @@ public @interface Excel
*/ */
public String separator() default ","; public String separator() default ",";
/**
* BigDecimal 精度 默认:-1(默认不开启BigDecimal格式化)
*/
public int scale() default -1;
/**
* BigDecimal 舍入规则 默认:BigDecimal.ROUND_HALF_EVEN
*/
public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
/** /**
* 导出类型0数字 1字符串 * 导出类型0数字 1字符串
*/ */
@@ -84,6 +96,42 @@ public @interface Excel
*/ */
public String targetAttr() default ""; public String targetAttr() default "";
/**
* 是否自动统计数据,在最后追加一行统计数据总和
*/
public boolean isStatistics() default false;
/**
* 导出字段对齐方式0默认1靠左2居中3靠右
*/
public Align align() default Align.AUTO;
/**
* 自定义数据处理器
*/
public Class<?> handler() default ExcelHandlerAdapter.class;
/**
* 自定义数据处理器参数
*/
public String[] args() default {};
public enum Align
{
AUTO(0), LEFT(1), CENTER(2), RIGHT(3);
private final int value;
Align(int value)
{
this.value = value;
}
public int value()
{
return this.value;
}
}
/** /**
* 字段类型0导出导入1仅导出2仅导入 * 字段类型0导出导入1仅导出2仅导入
*/ */
@@ -107,7 +155,7 @@ public @interface Excel
public enum ColumnType public enum ColumnType
{ {
NUMERIC(0), STRING(1); NUMERIC(0), STRING(1), IMAGE(2);
private final int value; private final int value;
ColumnType(int value) ColumnType(int value)

View File

@@ -8,12 +8,17 @@ package com.ruoyi.common.core.constant;
public class CacheConstants public class CacheConstants
{ {
/** /**
* oauth 缓存前缀 * 缓存有效期默认720分钟
*/ */
public static final String OAUTH_ACCESS = "oauth:access:"; public final static long EXPIRATION = 720;
/** /**
* oauth 客户端信息 * 缓存刷新时间默认120分钟
*/ */
public static final String CLIENT_DETAILS_KEY = "oauth:client:details"; public final static long REFRESH_TIME = 120;
/**
* 权限缓存前缀
*/
public final static String LOGIN_TOKEN_KEY = "login_tokens:";
} }

View File

@@ -17,6 +17,16 @@ public class Constants
*/ */
public static final String GBK = "GBK"; public static final String GBK = "GBK";
/**
* RMI 远程方法调用
*/
public static final String LOOKUP_RMI = "rmi://";
/**
* LDAP 远程方法调用
*/
public static final String LOOKUP_LDAP = "ldap://";
/** /**
* http请求 * http请求
*/ */
@@ -85,7 +95,8 @@ public class Constants
/** /**
* 验证码有效期(分钟) * 验证码有效期(分钟)
*/ */
public static final Integer CAPTCHA_EXPIRATION = 2; public static final long CAPTCHA_EXPIRATION = 2;
/** /**
* 参数管理 cache key * 参数管理 cache key
@@ -101,4 +112,10 @@ public class Constants
* 资源映射路径 前缀 * 资源映射路径 前缀
*/ */
public static final String RESOURCE_PREFIX = "/profile"; public static final String RESOURCE_PREFIX = "/profile";
/**
* 定时任务违规的字符
*/
public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
"org.springframework.jndi" };
} }

View File

@@ -13,6 +13,9 @@ public class GenConstants
/** 树表(增删改查) */ /** 树表(增删改查) */
public static final String TPL_TREE = "tree"; public static final String TPL_TREE = "tree";
/** 主子表(增删改查) */
public static final String TPL_SUB = "sub";
/** 树编码字段 */ /** 树编码字段 */
public static final String TREE_CODE = "treeCode"; public static final String TREE_CODE = "treeCode";
@@ -29,15 +32,17 @@ public class GenConstants
public static final String PARENT_MENU_NAME = "parentMenuName"; public static final String PARENT_MENU_NAME = "parentMenuName";
/** 数据库字符串类型 */ /** 数据库字符串类型 */
public static final String[] COLUMNTYPE_STR = { "char", "varchar", "narchar", "varchar2", "tinytext", "text", public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" };
"mediumtext", "longtext" };
/** 数据库文本类型 */
public static final String[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext" };
/** 数据库时间类型 */ /** 数据库时间类型 */
public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" }; public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" };
/** 数据库数字类型 */ /** 数据库数字类型 */
public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer", public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer",
"bigint", "float", "float", "double", "decimal" }; "bigint", "float", "double", "decimal" };
/** 页面不需要编辑字段 */ /** 页面不需要编辑字段 */
public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" }; public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" };
@@ -74,6 +79,15 @@ public class GenConstants
/** 日期控件 */ /** 日期控件 */
public static final String HTML_DATETIME = "datetime"; public static final String HTML_DATETIME = "datetime";
/** 图片上传控件 */
public static final String HTML_IMAGE_UPLOAD = "imageUpload";
/** 文件上传控件 */
public static final String HTML_FILE_UPLOAD = "fileUpload";
/** 富文本控件 */
public static final String HTML_EDITOR = "editor";
/** 字符串类型 */ /** 字符串类型 */
public static final String TYPE_STRING = "String"; public static final String TYPE_STRING = "String";

View File

@@ -7,21 +7,6 @@ package com.ruoyi.common.core.constant;
*/ */
public class SecurityConstants public class SecurityConstants
{ {
/**
* 令牌类型
*/
public static final String BEARER_TOKEN_TYPE = "Bearer";
/**
* 授权token url
*/
public static final String AUTH_TOKEN = "/oauth/token";
/**
* 注销token url
*/
public static final String TOKEN_LOGOUT = "/token/logout";
/** /**
* 用户ID字段 * 用户ID字段
*/ */
@@ -33,24 +18,27 @@ public class SecurityConstants
public static final String DETAILS_USERNAME = "username"; public static final String DETAILS_USERNAME = "username";
/** /**
* sys_oauth_client_details 表的字段不包括client_id、client_secret * 授权信息字段
*/ */
public static final String CLIENT_FIELDS = "client_id, client_secret, resource_ids, scope, " public static final String AUTHORIZATION_HEADER = "authorization";
+ "authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, "
+ "refresh_token_validity, additional_information, autoapprove";
/** /**
* JdbcClientDetailsService 查询语句 * 请求来源
*/ */
public static final String BASE_FIND_STATEMENT = "select " + CLIENT_FIELDS + " from sys_oauth_client_details"; public static final String FROM_SOURCE = "from-source";
/** /**
* 按条件client_id 查询 * 内部请求
*/ */
public static final String DEFAULT_SELECT_STATEMENT = BASE_FIND_STATEMENT + " where client_id = ?"; public static final String INNER = "inner";
/** /**
* 默认的查询语句 * 用户标识
*/ */
public static final String DEFAULT_FIND_STATEMENT = BASE_FIND_STATEMENT + " order by client_id"; public static final String USER_KEY = "user_key";
/**
* 登录用户
*/
public static final String LOGIN_USER = "login_user";
} }

View File

@@ -16,4 +16,9 @@ public class ServiceNameConstants
* 系统模块的serviceid * 系统模块的serviceid
*/ */
public static final String SYSTEM_SERVICE = "ruoyi-system"; public static final String SYSTEM_SERVICE = "ruoyi-system";
/**
* 文件服务的serviceid
*/
public static final String FILE_SERVICE = "ruoyi-file";
} }

View File

@@ -0,0 +1,25 @@
package com.ruoyi.common.core.constant;
/**
* Token的Key常量
*
* @author ruoyi
*/
public class TokenConstants
{
/**
* 令牌自定义标识
*/
public static final String AUTHENTICATION = "Authorization";
/**
* 令牌前缀
*/
public static final String PREFIX = "Bearer ";
/**
* 令牌秘钥
*/
public final static String SECRET = "abcdefghijklmnopqrstuvwxyz";
}

View File

@@ -54,7 +54,28 @@ public class UserConstants
/** Layout组件标识 */ /** Layout组件标识 */
public final static String LAYOUT = "Layout"; public final static String LAYOUT = "Layout";
/** ParentView组件标识 */
public final static String PARENT_VIEW = "ParentView";
/** InnerLink组件标识 */
public final static String INNER_LINK = "InnerLink";
/** 校验返回结果码 */ /** 校验返回结果码 */
public final static String UNIQUE = "0"; public final static String UNIQUE = "0";
public final static String NOT_UNIQUE = "1"; public final static String NOT_UNIQUE = "1";
/**
* 用户名长度限制
*/
public static final int USERNAME_MIN_LENGTH = 2;
public static final int USERNAME_MAX_LENGTH = 20;
/**
* 密码长度限制
*/
public static final int PASSWORD_MIN_LENGTH = 5;
public static final int PASSWORD_MAX_LENGTH = 20;
} }

View File

@@ -0,0 +1,88 @@
package com.ruoyi.common.core.context;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.alibaba.ttl.TransmittableThreadLocal;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.core.utils.StringUtils;
/**
* 获取当前线程变量中的 用户id、用户名称、Token等信息
* 注意: 必须在网关通过请求头的方法传入同时在HeaderInterceptor拦截器设置值。 否则这里无法获取
*
* @author ruoyi
*/
public class SecurityContextHolder
{
private static final TransmittableThreadLocal<Map<String, Object>> THREAD_LOCAL = new TransmittableThreadLocal<>();
public static void set(String key, Object value)
{
Map<String, Object> map = getLocalMap();
map.put(key, value == null ? StringUtils.EMPTY : value);
}
public static String get(String key)
{
Map<String, Object> map = getLocalMap();
return Convert.toStr(map.getOrDefault(key, StringUtils.EMPTY));
}
public static <T> T get(String key, Class<T> clazz)
{
Map<String, Object> map = getLocalMap();
return StringUtils.cast(map.getOrDefault(key, null));
}
public static Map<String, Object> getLocalMap()
{
Map<String, Object> map = THREAD_LOCAL.get();
if (map == null)
{
map = new ConcurrentHashMap<String, Object>();
THREAD_LOCAL.set(map);
}
return map;
}
public static void setLocalMap(Map<String, Object> threadLocalMap)
{
THREAD_LOCAL.set(threadLocalMap);
}
public static Long getUserId()
{
return Convert.toLong(get(SecurityConstants.DETAILS_USER_ID), 0L);
}
public static void setUserId(String account)
{
set(SecurityConstants.DETAILS_USER_ID, account);
}
public static String getUserName()
{
return get(SecurityConstants.DETAILS_USERNAME);
}
public static void setUserName(String username)
{
set(SecurityConstants.DETAILS_USERNAME, username);
}
public static String getUserKey()
{
return get(SecurityConstants.USER_KEY);
}
public static void setUserKey(String userKey)
{
set(SecurityConstants.USER_KEY, userKey);
}
public static void remove()
{
THREAD_LOCAL.remove();
}
}

View File

@@ -1,43 +0,0 @@
package com.ruoyi.common.core.exception;
/**
* 自定义异常
*
* @author ruoyi
*/
public class CustomException extends RuntimeException
{
private static final long serialVersionUID = 1L;
private Integer code;
private String message;
public CustomException(String message)
{
this.message = message;
}
public CustomException(String message, Integer code)
{
this.message = message;
this.code = code;
}
public CustomException(String message, Throwable e)
{
super(message, e);
this.message = message;
}
@Override
public String getMessage()
{
return message;
}
public Integer getCode()
{
return code;
}
}

View File

@@ -0,0 +1,58 @@
package com.ruoyi.common.core.exception;
/**
* 全局异常
*
* @author ruoyi
*/
public class GlobalException extends RuntimeException
{
private static final long serialVersionUID = 1L;
/**
* 错误提示
*/
private String message;
/**
* 错误明细,内部调试错误
*
* 和 {@link CommonResult#getDetailMessage()} 一致的设计
*/
private String detailMessage;
/**
* 空构造方法,避免反序列化问题
*/
public GlobalException()
{
}
public GlobalException(String message)
{
this.message = message;
}
public String getDetailMessage()
{
return detailMessage;
}
public GlobalException setDetailMessage(String detailMessage)
{
this.detailMessage = detailMessage;
return this;
}
public String getMessage()
{
return message;
}
public GlobalException setMessage(String message)
{
this.message = message;
return this;
}
}

View File

@@ -0,0 +1,16 @@
package com.ruoyi.common.core.exception;
/**
* 内部认证异常
*
* @author ruoyi
*/
public class InnerAuthException extends RuntimeException
{
private static final long serialVersionUID = 1L;
public InnerAuthException(String message)
{
super(message);
}
}

View File

@@ -0,0 +1,15 @@
package com.ruoyi.common.core.exception;
/**
* 权限异常
*
* @author ruoyi
*/
public class PreAuthorizeException extends RuntimeException
{
private static final long serialVersionUID = 1L;
public PreAuthorizeException()
{
}
}

View File

@@ -0,0 +1,73 @@
package com.ruoyi.common.core.exception;
/**
* 业务异常
*
* @author ruoyi
*/
public final class ServiceException extends RuntimeException
{
private static final long serialVersionUID = 1L;
/**
* 错误码
*/
private Integer code;
/**
* 错误提示
*/
private String message;
/**
* 错误明细,内部调试错误
*
* 和 {@link CommonResult#getDetailMessage()} 一致的设计
*/
private String detailMessage;
/**
* 空构造方法,避免反序列化问题
*/
public ServiceException()
{
}
public ServiceException(String message)
{
this.message = message;
}
public ServiceException(String message, Integer code)
{
this.message = message;
this.code = code;
}
public String getDetailMessage()
{
return detailMessage;
}
public String getMessage()
{
return message;
}
public Integer getCode()
{
return code;
}
public ServiceException setMessage(String message)
{
this.message = message;
return this;
}
public ServiceException setDetailMessage(String detailMessage)
{
this.detailMessage = detailMessage;
return this;
}
}

View File

@@ -0,0 +1,16 @@
package com.ruoyi.common.core.exception.auth;
/**
* 未能通过的登录认证异常
*
* @author ruoyi
*/
public class NotLoginException extends RuntimeException
{
private static final long serialVersionUID = 1L;
public NotLoginException(String message)
{
super(message);
}
}

View File

@@ -0,0 +1,23 @@
package com.ruoyi.common.core.exception.auth;
import org.apache.commons.lang3.StringUtils;
/**
* 未能通过的权限认证异常
*
* @author ruoyi
*/
public class NotPermissionException extends RuntimeException
{
private static final long serialVersionUID = 1L;
public NotPermissionException(String permission)
{
super(permission);
}
public NotPermissionException(String[] permissions)
{
super(StringUtils.join(permissions, ","));
}
}

View File

@@ -0,0 +1,23 @@
package com.ruoyi.common.core.exception.auth;
import org.apache.commons.lang3.StringUtils;
/**
* 未能通过的角色认证异常
*
* @author ruoyi
*/
public class NotRoleException extends RuntimeException
{
private static final long serialVersionUID = 1L;
public NotRoleException(String role)
{
super(role);
}
public NotRoleException(String[] roles)
{
super(StringUtils.join(roles, ","));
}
}

View File

@@ -1,79 +1,79 @@
package com.ruoyi.common.core.exception; package com.ruoyi.common.core.exception.base;
/** /**
* 基础异常 * 基础异常
* *
* @author ruoyi * @author ruoyi
*/ */
public class BaseException extends RuntimeException public class BaseException extends RuntimeException
{ {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/** /**
* 所属模块 * 所属模块
*/ */
private String module; private String module;
/** /**
* 错误码 * 错误码
*/ */
private String code; private String code;
/** /**
* 错误码对应的参数 * 错误码对应的参数
*/ */
private Object[] args; private Object[] args;
/** /**
* 错误消息 * 错误消息
*/ */
private String defaultMessage; private String defaultMessage;
public BaseException(String module, String code, Object[] args, String defaultMessage) public BaseException(String module, String code, Object[] args, String defaultMessage)
{ {
this.module = module; this.module = module;
this.code = code; this.code = code;
this.args = args; this.args = args;
this.defaultMessage = defaultMessage; this.defaultMessage = defaultMessage;
} }
public BaseException(String module, String code, Object[] args) public BaseException(String module, String code, Object[] args)
{ {
this(module, code, args, null); this(module, code, args, null);
} }
public BaseException(String module, String defaultMessage) public BaseException(String module, String defaultMessage)
{ {
this(module, null, null, defaultMessage); this(module, null, null, defaultMessage);
} }
public BaseException(String code, Object[] args) public BaseException(String code, Object[] args)
{ {
this(null, code, args, null); this(null, code, args, null);
} }
public BaseException(String defaultMessage) public BaseException(String defaultMessage)
{ {
this(null, null, null, defaultMessage); this(null, null, null, defaultMessage);
} }
public String getModule() public String getModule()
{ {
return module; return module;
} }
public String getCode() public String getCode()
{ {
return code; return code;
} }
public Object[] getArgs() public Object[] getArgs()
{ {
return args; return args;
} }
public String getDefaultMessage() public String getDefaultMessage()
{ {
return defaultMessage; return defaultMessage;
} }
} }

View File

@@ -0,0 +1,19 @@
package com.ruoyi.common.core.exception.file;
import com.ruoyi.common.core.exception.base.BaseException;
/**
* 文件信息异常类
*
* @author ruoyi
*/
public class FileException extends BaseException
{
private static final long serialVersionUID = 1L;
public FileException(String code, Object[] args)
{
super("file", code, args, null);
}
}

View File

@@ -0,0 +1,16 @@
package com.ruoyi.common.core.exception.file;
/**
* 文件名称超长限制异常类
*
* @author ruoyi
*/
public class FileNameLengthLimitExceededException extends FileException
{
private static final long serialVersionUID = 1L;
public FileNameLengthLimitExceededException(int defaultFileNameLength)
{
super("upload.filename.exceed.length", new Object[] { defaultFileNameLength });
}
}

View File

@@ -0,0 +1,16 @@
package com.ruoyi.common.core.exception.file;
/**
* 文件名大小限制异常类
*
* @author ruoyi
*/
public class FileSizeLimitExceededException extends FileException
{
private static final long serialVersionUID = 1L;
public FileSizeLimitExceededException(long defaultMaxSize)
{
super("upload.exceed.maxSize", new Object[] { defaultMaxSize });
}
}

View File

@@ -0,0 +1,81 @@
package com.ruoyi.common.core.exception.file;
import java.util.Arrays;
import org.apache.commons.fileupload.FileUploadException;
/**
* 文件上传 误异常类
*
* @author ruoyi
*/
public class InvalidExtensionException extends FileUploadException
{
private static final long serialVersionUID = 1L;
private String[] allowedExtension;
private String extension;
private String filename;
public InvalidExtensionException(String[] allowedExtension, String extension, String filename)
{
super("filename : [" + filename + "], extension : [" + extension + "], allowed extension : [" + Arrays.toString(allowedExtension) + "]");
this.allowedExtension = allowedExtension;
this.extension = extension;
this.filename = filename;
}
public String[] getAllowedExtension()
{
return allowedExtension;
}
public String getExtension()
{
return extension;
}
public String getFilename()
{
return filename;
}
public static class InvalidImageExtensionException extends InvalidExtensionException
{
private static final long serialVersionUID = 1L;
public InvalidImageExtensionException(String[] allowedExtension, String extension, String filename)
{
super(allowedExtension, extension, filename);
}
}
public static class InvalidFlashExtensionException extends InvalidExtensionException
{
private static final long serialVersionUID = 1L;
public InvalidFlashExtensionException(String[] allowedExtension, String extension, String filename)
{
super(allowedExtension, extension, filename);
}
}
public static class InvalidMediaExtensionException extends InvalidExtensionException
{
private static final long serialVersionUID = 1L;
public InvalidMediaExtensionException(String[] allowedExtension, String extension, String filename)
{
super(allowedExtension, extension, filename);
}
}
public static class InvalidVideoExtensionException extends InvalidExtensionException
{
private static final long serialVersionUID = 1L;
public InvalidVideoExtensionException(String[] allowedExtension, String extension, String filename)
{
super(allowedExtension, extension, filename);
}
}
}

View File

@@ -1,6 +1,6 @@
package com.ruoyi.common.core.exception.user; package com.ruoyi.common.core.exception.user;
import com.ruoyi.common.core.exception.BaseException; import com.ruoyi.common.core.exception.base.BaseException;
/** /**
* 用户信息异常类 * 用户信息异常类

View File

@@ -66,7 +66,7 @@ public class CharsetKit
if (null == destCharset) if (null == destCharset)
{ {
srcCharset = StandardCharsets.UTF_8; destCharset = StandardCharsets.UTF_8;
} }
if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset)) if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset))

View File

@@ -797,7 +797,21 @@ public class Convert
} }
else if (obj instanceof byte[] || obj instanceof Byte[]) else if (obj instanceof byte[] || obj instanceof Byte[])
{ {
return str((Byte[]) obj, charset); if (obj instanceof byte[])
{
return str((byte[]) obj, charset);
}
else
{
Byte[] bytes = (Byte[]) obj;
int length = bytes.length;
byte[] dest = new byte[length];
for (int i = 0; i < length; i++)
{
dest[i] = bytes[i];
}
return str(dest, charset);
}
} }
else if (obj instanceof ByteBuffer) else if (obj instanceof ByteBuffer)
{ {

View File

@@ -22,7 +22,7 @@ public class ExceptionUtil
return str; return str;
} }
public static String getRootErrorMseeage(Exception e) public static String getRootErrorMessage(Exception e)
{ {
Throwable root = ExceptionUtils.getRootCause(e); Throwable root = ExceptionUtils.getRootCause(e);
root = (root == null ? e : root); root = (root == null ? e : root);

View File

@@ -0,0 +1,123 @@
package com.ruoyi.common.core.utils;
import java.util.Map;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.constant.TokenConstants;
import com.ruoyi.common.core.text.Convert;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
/**
* Jwt工具类
*
* @author ruoyi
*/
public class JwtUtils
{
public static String secret = TokenConstants.SECRET;
/**
* 从数据声明生成令牌
*
* @param claims 数据声明
* @return 令牌
*/
public static String createToken(Map<String, Object> claims)
{
String token = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512, secret).compact();
return token;
}
/**
* 从令牌中获取数据声明
*
* @param token 令牌
* @return 数据声明
*/
public static Claims parseToken(String token)
{
return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
}
/**
* 根据令牌获取用户标识
*
* @param token 令牌
* @return 用户ID
*/
public static String getUserKey(String token)
{
Claims claims = parseToken(token);
return getValue(claims, SecurityConstants.USER_KEY);
}
/**
* 根据令牌获取用户标识
*
* @param claims 身份信息
* @return 用户ID
*/
public static String getUserKey(Claims claims)
{
return getValue(claims, SecurityConstants.USER_KEY);
}
/**
* 根据令牌获取用户ID
*
* @param token 令牌
* @return 用户ID
*/
public static String getUserId(String token)
{
Claims claims = parseToken(token);
return getValue(claims, SecurityConstants.DETAILS_USER_ID);
}
/**
* 根据身份信息获取用户ID
*
* @param claims 身份信息
* @return 用户ID
*/
public static String getUserId(Claims claims)
{
return getValue(claims, SecurityConstants.DETAILS_USER_ID);
}
/**
* 根据令牌获取用户名
*
* @param token 令牌
* @return 用户名
*/
public static String getUserName(String token)
{
Claims claims = parseToken(token);
return getValue(claims, SecurityConstants.DETAILS_USERNAME);
}
/**
* 根据身份信息获取用户名
*
* @param claims 身份信息
* @return 用户名
*/
public static String getUserName(Claims claims)
{
return getValue(claims, SecurityConstants.DETAILS_USERNAME);
}
/**
* 根据身份信息获取键值
*
* @param claims 身份信息
* @param key 键
* @return 值
*/
public static String getValue(Claims claims, String key)
{
return Convert.toStr(claims.get(key), "");
}
}

View File

@@ -1,13 +1,28 @@
package com.ruoyi.common.core.utils; package com.ruoyi.common.core.utils;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSession;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.context.request.ServletRequestAttributes;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.text.Convert; import com.ruoyi.common.core.text.Convert;
import reactor.core.publisher.Mono;
/** /**
* 客户端工具类 * 客户端工具类
@@ -48,12 +63,35 @@ public class ServletUtils
return Convert.toInt(getRequest().getParameter(name), defaultValue); return Convert.toInt(getRequest().getParameter(name), defaultValue);
} }
/**
* 获取Boolean参数
*/
public static Boolean getParameterToBool(String name)
{
return Convert.toBool(getRequest().getParameter(name));
}
/**
* 获取Boolean参数
*/
public static Boolean getParameterToBool(String name, Boolean defaultValue)
{
return Convert.toBool(getRequest().getParameter(name), defaultValue);
}
/** /**
* 获取request * 获取request
*/ */
public static HttpServletRequest getRequest() public static HttpServletRequest getRequest()
{ {
return getRequestAttributes().getRequest(); try
{
return getRequestAttributes().getRequest();
}
catch (Exception e)
{
return null;
}
} }
/** /**
@@ -61,7 +99,14 @@ public class ServletUtils
*/ */
public static HttpServletResponse getResponse() public static HttpServletResponse getResponse()
{ {
return getRequestAttributes().getResponse(); try
{
return getRequestAttributes().getResponse();
}
catch (Exception e)
{
return null;
}
} }
/** /**
@@ -74,8 +119,41 @@ public class ServletUtils
public static ServletRequestAttributes getRequestAttributes() public static ServletRequestAttributes getRequestAttributes()
{ {
RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); try
return (ServletRequestAttributes) attributes; {
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
return (ServletRequestAttributes) attributes;
}
catch (Exception e)
{
return null;
}
}
public static String getHeader(HttpServletRequest request, String name)
{
String value = request.getHeader(name);
if (StringUtils.isEmpty(value))
{
return StringUtils.EMPTY;
}
return urlDecode(value);
}
public static Map<String, String> getHeaders(HttpServletRequest request)
{
Map<String, String> map = new LinkedHashMap<>();
Enumeration<String> enumeration = request.getHeaderNames();
if (enumeration != null)
{
while (enumeration.hasMoreElements())
{
String key = enumeration.nextElement();
String value = request.getHeader(key);
map.put(key, value);
}
}
return map;
} }
/** /**
@@ -133,4 +211,98 @@ public class ServletUtils
} }
return false; return false;
} }
/**
* 内容编码
*
* @param str 内容
* @return 编码后的内容
*/
public static String urlEncode(String str)
{
try
{
return URLEncoder.encode(str, Constants.UTF8);
}
catch (UnsupportedEncodingException e)
{
return StringUtils.EMPTY;
}
}
/**
* 内容解码
*
* @param str 内容
* @return 解码后的内容
*/
public static String urlDecode(String str)
{
try
{
return URLDecoder.decode(str, Constants.UTF8);
}
catch (UnsupportedEncodingException e)
{
return StringUtils.EMPTY;
}
}
/**
* 设置webflux模型响应
*
* @param response ServerHttpResponse
* @param value 响应内容
* @return Mono<Void>
*/
public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, Object value)
{
return webFluxResponseWriter(response, HttpStatus.OK, value, R.FAIL);
}
/**
* 设置webflux模型响应
*
* @param response ServerHttpResponse
* @param code 响应状态码
* @param value 响应内容
* @return Mono<Void>
*/
public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, Object value, int code)
{
return webFluxResponseWriter(response, HttpStatus.OK, value, code);
}
/**
* 设置webflux模型响应
*
* @param response ServerHttpResponse
* @param status http状态码
* @param code 响应状态码
* @param value 响应内容
* @return Mono<Void>
*/
public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, HttpStatus status, Object value, int code)
{
return webFluxResponseWriter(response, MediaType.APPLICATION_JSON_VALUE, status, value, code);
}
/**
* 设置webflux模型响应
*
* @param response ServerHttpResponse
* @param contentType content-type
* @param status http状态码
* @param code 响应状态码
* @param value 响应内容
* @return Mono<Void>
*/
public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, String contentType, HttpStatus status, Object value, int code)
{
response.setStatusCode(status);
response.getHeaders().add(HttpHeaders.CONTENT_TYPE, contentType);
R<?> result = R.fail(code, value.toString());
DataBuffer dataBuffer = response.bufferFactory().wrap(JSONObject.toJSONString(result).getBytes());
return response.writeWith(Mono.just(dataBuffer));
}
} }

View File

@@ -1,7 +1,10 @@
package com.ruoyi.common.core.utils; package com.ruoyi.common.core.utils;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.springframework.util.AntPathMatcher;
import com.ruoyi.common.core.constant.Constants;
import com.ruoyi.common.core.text.StrFormatter; import com.ruoyi.common.core.text.StrFormatter;
/** /**
@@ -234,6 +237,30 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
return str.substring(start, end); return str.substring(start, end);
} }
/**
* 判断是否为空,并且不是空白字符
*
* @param str 要判断的value
* @return 结果
*/
public static boolean hasText(String str)
{
return (str != null && !str.isEmpty() && containsText(str));
}
private static boolean containsText(CharSequence str)
{
int strLen = str.length();
for (int i = 0; i < strLen; i++)
{
if (!Character.isWhitespace(str.charAt(i)))
{
return true;
}
}
return false;
}
/** /**
* 格式化文本, {} 表示占位符<br> * 格式化文本, {} 表示占位符<br>
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br> * 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
@@ -257,7 +284,18 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
} }
/** /**
* 下划线转驼峰命名 * 是否为http(s)://开头
*
* @param link 链接
* @return 结果
*/
public static boolean ishttp(String link)
{
return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS);
}
/**
* 驼峰转下划线命名
*/ */
public static String toUnderScoreCase(String str) public static String toUnderScoreCase(String str)
{ {
@@ -396,6 +434,45 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
return sb.toString(); return sb.toString();
} }
/**
* 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
*
* @param str 指定字符串
* @param strs 需要检查的字符串数组
* @return 是否匹配
*/
public static boolean matches(String str, List<String> strs)
{
if (isEmpty(str) || isEmpty(strs))
{
return false;
}
for (String pattern : strs)
{
if (isMatch(pattern, str))
{
return true;
}
}
return false;
}
/**
* 判断url是否与规则配置:
* ? 表示单个字符;
* * 表示一层路径内的任意字符串,不可跨层级;
* ** 表示任意层路径;
*
* @param pattern 匹配规则
* @param url 需要匹配的url
* @return
*/
public static boolean isMatch(String pattern, String url)
{
AntPathMatcher matcher = new AntPathMatcher();
return matcher.match(pattern, url);
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T> T cast(Object obj) public static <T> T cast(Object obj)
{ {

View File

@@ -0,0 +1,76 @@
package com.ruoyi.common.core.utils.file;
import java.io.File;
import org.apache.commons.lang3.StringUtils;
/**
* 文件类型工具类
*
* @author ruoyi
*/
public class FileTypeUtils
{
/**
* 获取文件类型
* <p>
* 例如: ruoyi.txt, 返回: txt
*
* @param file 文件名
* @return 后缀(不含".")
*/
public static String getFileType(File file)
{
if (null == file)
{
return StringUtils.EMPTY;
}
return getFileType(file.getName());
}
/**
* 获取文件类型
* <p>
* 例如: ruoyi.txt, 返回: txt
*
* @param fileName 文件名
* @return 后缀(不含".")
*/
public static String getFileType(String fileName)
{
int separatorIndex = fileName.lastIndexOf(".");
if (separatorIndex < 0)
{
return "";
}
return fileName.substring(separatorIndex + 1).toLowerCase();
}
/**
* 获取文件类型
*
* @param photoByte 文件字节码
* @return 后缀(不含".")
*/
public static String getFileExtendName(byte[] photoByte)
{
String strFileExtendName = "JPG";
if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
&& ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97))
{
strFileExtendName = "GIF";
}
else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70))
{
strFileExtendName = "JPG";
}
else if ((photoByte[0] == 66) && (photoByte[1] == 77))
{
strFileExtendName = "BMP";
}
else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71))
{
strFileExtendName = "PNG";
}
return strFileExtendName;
}
}

View File

@@ -7,15 +7,25 @@ import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.ArrayUtils;
import com.ruoyi.common.core.utils.StringUtils;
/** /**
* 文件处理工具类 * 文件处理工具类
* *
* @author ruoyi * @author ruoyi
*/ */
public class FileUtils extends org.apache.commons.io.FileUtils public class FileUtils
{ {
/** 字符常量:斜杠 {@code '/'} */
public static final char SLASH = '/';
/** 字符常量:反斜杠 {@code '\\'} */
public static final char BACKSLASH = '\\';
public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+"; public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
/** /**
@@ -104,6 +114,30 @@ public class FileUtils extends org.apache.commons.io.FileUtils
return filename.matches(FILENAME_PATTERN); return filename.matches(FILENAME_PATTERN);
} }
/**
* 检查文件是否可下载
*
* @param resource 需要下载的文件
* @return true 正常 false 非法
*/
public static boolean checkAllowDownload(String resource)
{
// 禁止目录上跳级别
if (StringUtils.contains(resource, ".."))
{
return false;
}
// 检查允许下载的文件规则
if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource)))
{
return true;
}
// 不在允许下载的文件规则
return false;
}
/** /**
* 下载文件名重新编码 * 下载文件名重新编码
* *
@@ -111,8 +145,7 @@ public class FileUtils extends org.apache.commons.io.FileUtils
* @param fileName 文件名 * @param fileName 文件名
* @return 编码后的文件名 * @return 编码后的文件名
*/ */
public static String setFileDownloadHeader(HttpServletRequest request, String fileName) public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException
throws UnsupportedEncodingException
{ {
final String agent = request.getHeader("USER-AGENT"); final String agent = request.getHeader("USER-AGENT");
String filename = fileName; String filename = fileName;
@@ -139,4 +172,90 @@ public class FileUtils extends org.apache.commons.io.FileUtils
} }
return filename; return filename;
} }
/**
* 返回文件名
*
* @param filePath 文件
* @return 文件名
*/
public static String getName(String filePath)
{
if (null == filePath)
{
return null;
}
int len = filePath.length();
if (0 == len)
{
return filePath;
}
if (isFileSeparator(filePath.charAt(len - 1)))
{
// 以分隔符结尾的去掉结尾分隔符
len--;
}
int begin = 0;
char c;
for (int i = len - 1; i > -1; i--)
{
c = filePath.charAt(i);
if (isFileSeparator(c))
{
// 查找最后一个路径分隔符(/或者\
begin = i + 1;
break;
}
}
return filePath.substring(begin, len);
}
/**
* 是否为Windows或者LinuxUnix文件分隔符<br>
* Windows平台下分隔符为\LinuxUnix为/
*
* @param c 字符
* @return 是否为Windows或者LinuxUnix文件分隔符
*/
public static boolean isFileSeparator(char c)
{
return SLASH == c || BACKSLASH == c;
}
/**
* 下载文件名重新编码
*
* @param response 响应对象
* @param realFileName 真实文件名
* @return
*/
public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException
{
String percentEncodedFileName = percentEncode(realFileName);
StringBuilder contentDispositionValue = new StringBuilder();
contentDispositionValue.append("attachment; filename=")
.append(percentEncodedFileName)
.append(";")
.append("filename*=")
.append("utf-8''")
.append(percentEncodedFileName);
response.setHeader("Content-disposition", contentDispositionValue.toString());
response.setHeader("download-filename", percentEncodedFileName);
}
/**
* 百分号编码工具方法
*
* @param s 需要百分号编码的字符串
* @return 百分号编码后的字符串
*/
public static String percentEncode(String s) throws UnsupportedEncodingException
{
String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
return encode.replaceAll("\\+", "%20");
}
} }

Some files were not shown because too many files have changed in this diff Show More