Commit c925b3d1e8967189542f467e12357d9526e5fa14
1 parent
940773b4
JeecgBoot 3.3.0 版本发布(发布日期:20220725)
Showing
40 changed files
with
1023 additions
and
200 deletions
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/api/dto/message/MessageDTO.java
@@ -4,6 +4,7 @@ import lombok.Data; | @@ -4,6 +4,7 @@ import lombok.Data; | ||
4 | import org.jeecg.common.constant.CommonConstant; | 4 | import org.jeecg.common.constant.CommonConstant; |
5 | 5 | ||
6 | import java.io.Serializable; | 6 | import java.io.Serializable; |
7 | +import java.util.Map; | ||
7 | 8 | ||
8 | /** | 9 | /** |
9 | * 普通消息 | 10 | * 普通消息 |
@@ -72,4 +73,18 @@ public class MessageDTO implements Serializable { | @@ -72,4 +73,18 @@ public class MessageDTO implements Serializable { | ||
72 | this.category = category; | 73 | this.category = category; |
73 | } | 74 | } |
74 | 75 | ||
76 | + /** | ||
77 | + * 模板消息对应的模板编码 | ||
78 | + */ | ||
79 | + protected String templateCode; | ||
80 | + /** | ||
81 | + * 消息类型:org.jeecg.common.constant.enums.MessageTypeEnum | ||
82 | + */ | ||
83 | + protected String type; | ||
84 | + | ||
85 | + /** | ||
86 | + * 解析模板内容 对应的数据 | ||
87 | + */ | ||
88 | + protected Map<String, Object> data; | ||
89 | + | ||
75 | } | 90 | } |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/aspect/PermissionDataAspect.java
@@ -40,6 +40,8 @@ public class PermissionDataAspect { | @@ -40,6 +40,8 @@ public class PermissionDataAspect { | ||
40 | @Autowired | 40 | @Autowired |
41 | private CommonAPI commonApi; | 41 | private CommonAPI commonApi; |
42 | 42 | ||
43 | + private static final String SPOT_DO = ".do"; | ||
44 | + | ||
43 | @Pointcut("@annotation(org.jeecg.common.aspect.annotation.PermissionData)") | 45 | @Pointcut("@annotation(org.jeecg.common.aspect.annotation.PermissionData)") |
44 | public void pointCut() { | 46 | public void pointCut() { |
45 | 47 | ||
@@ -113,7 +115,7 @@ public class PermissionDataAspect { | @@ -113,7 +115,7 @@ public class PermissionDataAspect { | ||
113 | requestPath = requestPath.substring(0, requestPath.indexOf("&")); | 115 | requestPath = requestPath.substring(0, requestPath.indexOf("&")); |
114 | } | 116 | } |
115 | if(requestPath.indexOf(QueryRuleEnum.EQ.getValue())!=-1){ | 117 | if(requestPath.indexOf(QueryRuleEnum.EQ.getValue())!=-1){ |
116 | - if(requestPath.indexOf(CommonConstant.SPOT_DO)!=-1){ | 118 | + if(requestPath.indexOf(SPOT_DO)!=-1){ |
117 | requestPath = requestPath.substring(0,requestPath.indexOf(".do")+3); | 119 | requestPath = requestPath.substring(0,requestPath.indexOf(".do")+3); |
118 | }else{ | 120 | }else{ |
119 | requestPath = requestPath.substring(0,requestPath.indexOf("?")); | 121 | requestPath = requestPath.substring(0,requestPath.indexOf("?")); |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/aspect/annotation/DynamicTable.java
0 → 100644
1 | +package org.jeecg.common.aspect.annotation; | ||
2 | + | ||
3 | +import java.lang.annotation.*; | ||
4 | + | ||
5 | +/** | ||
6 | + * 动态table切换 | ||
7 | + * | ||
8 | + * @author :zyf | ||
9 | + * @date:2020-04-25 | ||
10 | + */ | ||
11 | +@Target(ElementType.METHOD) | ||
12 | +@Retention(RetentionPolicy.RUNTIME) | ||
13 | +@Documented | ||
14 | +public @interface DynamicTable { | ||
15 | + /** | ||
16 | + * 需要动态解析的表名 | ||
17 | + * @return | ||
18 | + */ | ||
19 | + String value(); | ||
20 | +} |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/CommonConstant.java
@@ -9,320 +9,321 @@ public interface CommonConstant { | @@ -9,320 +9,321 @@ public interface CommonConstant { | ||
9 | /** | 9 | /** |
10 | * 正常状态 | 10 | * 正常状态 |
11 | */ | 11 | */ |
12 | - public static final Integer STATUS_NORMAL = 0; | 12 | + Integer STATUS_NORMAL = 0; |
13 | 13 | ||
14 | /** | 14 | /** |
15 | * 禁用状态 | 15 | * 禁用状态 |
16 | */ | 16 | */ |
17 | - public static final Integer STATUS_DISABLE = -1; | 17 | + Integer STATUS_DISABLE = -1; |
18 | 18 | ||
19 | /** | 19 | /** |
20 | * 删除标志 | 20 | * 删除标志 |
21 | */ | 21 | */ |
22 | - public static final Integer DEL_FLAG_1 = 1; | 22 | + Integer DEL_FLAG_1 = 1; |
23 | 23 | ||
24 | /** | 24 | /** |
25 | * 未删除 | 25 | * 未删除 |
26 | */ | 26 | */ |
27 | - public static final Integer DEL_FLAG_0 = 0; | 27 | + Integer DEL_FLAG_0 = 0; |
28 | 28 | ||
29 | /** | 29 | /** |
30 | * 系统日志类型: 登录 | 30 | * 系统日志类型: 登录 |
31 | */ | 31 | */ |
32 | - public static final int LOG_TYPE_1 = 1; | 32 | + int LOG_TYPE_1 = 1; |
33 | 33 | ||
34 | /** | 34 | /** |
35 | * 系统日志类型: 操作 | 35 | * 系统日志类型: 操作 |
36 | */ | 36 | */ |
37 | - public static final int LOG_TYPE_2 = 2; | 37 | + int LOG_TYPE_2 = 2; |
38 | 38 | ||
39 | /** | 39 | /** |
40 | * 操作日志类型: 查询 | 40 | * 操作日志类型: 查询 |
41 | */ | 41 | */ |
42 | - public static final int OPERATE_TYPE_1 = 1; | 42 | + int OPERATE_TYPE_1 = 1; |
43 | 43 | ||
44 | /** | 44 | /** |
45 | * 操作日志类型: 添加 | 45 | * 操作日志类型: 添加 |
46 | */ | 46 | */ |
47 | - public static final int OPERATE_TYPE_2 = 2; | 47 | + int OPERATE_TYPE_2 = 2; |
48 | 48 | ||
49 | /** | 49 | /** |
50 | * 操作日志类型: 更新 | 50 | * 操作日志类型: 更新 |
51 | */ | 51 | */ |
52 | - public static final int OPERATE_TYPE_3 = 3; | 52 | + int OPERATE_TYPE_3 = 3; |
53 | 53 | ||
54 | /** | 54 | /** |
55 | * 操作日志类型: 删除 | 55 | * 操作日志类型: 删除 |
56 | */ | 56 | */ |
57 | - public static final int OPERATE_TYPE_4 = 4; | 57 | + int OPERATE_TYPE_4 = 4; |
58 | 58 | ||
59 | /** | 59 | /** |
60 | * 操作日志类型: 倒入 | 60 | * 操作日志类型: 倒入 |
61 | */ | 61 | */ |
62 | - public static final int OPERATE_TYPE_5 = 5; | 62 | + int OPERATE_TYPE_5 = 5; |
63 | 63 | ||
64 | /** | 64 | /** |
65 | * 操作日志类型: 导出 | 65 | * 操作日志类型: 导出 |
66 | */ | 66 | */ |
67 | - public static final int OPERATE_TYPE_6 = 6; | 67 | + int OPERATE_TYPE_6 = 6; |
68 | 68 | ||
69 | 69 | ||
70 | /** {@code 500 Server Error} (HTTP/1.0 - RFC 1945) */ | 70 | /** {@code 500 Server Error} (HTTP/1.0 - RFC 1945) */ |
71 | - public static final Integer SC_INTERNAL_SERVER_ERROR_500 = 500; | 71 | + Integer SC_INTERNAL_SERVER_ERROR_500 = 500; |
72 | /** {@code 200 OK} (HTTP/1.0 - RFC 1945) */ | 72 | /** {@code 200 OK} (HTTP/1.0 - RFC 1945) */ |
73 | - public static final Integer SC_OK_200 = 200; | 73 | + Integer SC_OK_200 = 200; |
74 | 74 | ||
75 | /**访问权限认证未通过 510*/ | 75 | /**访问权限认证未通过 510*/ |
76 | - public static final Integer SC_JEECG_NO_AUTHZ=510; | 76 | + Integer SC_JEECG_NO_AUTHZ=510; |
77 | 77 | ||
78 | /** 登录用户Shiro权限缓存KEY前缀 */ | 78 | /** 登录用户Shiro权限缓存KEY前缀 */ |
79 | public static String PREFIX_USER_SHIRO_CACHE = "shiro:cache:org.jeecg.config.shiro.ShiroRealm.authorizationCache:"; | 79 | public static String PREFIX_USER_SHIRO_CACHE = "shiro:cache:org.jeecg.config.shiro.ShiroRealm.authorizationCache:"; |
80 | /** 登录用户Token令牌缓存KEY前缀 */ | 80 | /** 登录用户Token令牌缓存KEY前缀 */ |
81 | - public static final String PREFIX_USER_TOKEN = "prefix_user_token_"; | 81 | + String PREFIX_USER_TOKEN = "prefix_user_token_"; |
82 | // /** Token缓存时间:3600秒即一小时 */ | 82 | // /** Token缓存时间:3600秒即一小时 */ |
83 | -// public static final int TOKEN_EXPIRE_TIME = 3600; | 83 | +// int TOKEN_EXPIRE_TIME = 3600; |
84 | 84 | ||
85 | /** 登录二维码 */ | 85 | /** 登录二维码 */ |
86 | - public static final String LOGIN_QRCODE_PRE = "QRCODELOGIN:"; | ||
87 | - public static final String LOGIN_QRCODE = "LQ:"; | 86 | + String LOGIN_QRCODE_PRE = "QRCODELOGIN:"; |
87 | + String LOGIN_QRCODE = "LQ:"; | ||
88 | /** 登录二维码token */ | 88 | /** 登录二维码token */ |
89 | - public static final String LOGIN_QRCODE_TOKEN = "LQT:"; | 89 | + String LOGIN_QRCODE_TOKEN = "LQT:"; |
90 | 90 | ||
91 | 91 | ||
92 | /** | 92 | /** |
93 | * 0:一级菜单 | 93 | * 0:一级菜单 |
94 | */ | 94 | */ |
95 | - public static final Integer MENU_TYPE_0 = 0; | 95 | + Integer MENU_TYPE_0 = 0; |
96 | /** | 96 | /** |
97 | * 1:子菜单 | 97 | * 1:子菜单 |
98 | */ | 98 | */ |
99 | - public static final Integer MENU_TYPE_1 = 1; | 99 | + Integer MENU_TYPE_1 = 1; |
100 | /** | 100 | /** |
101 | * 2:按钮权限 | 101 | * 2:按钮权限 |
102 | */ | 102 | */ |
103 | - public static final Integer MENU_TYPE_2 = 2; | 103 | + Integer MENU_TYPE_2 = 2; |
104 | 104 | ||
105 | /**通告对象类型(USER:指定用户,ALL:全体用户)*/ | 105 | /**通告对象类型(USER:指定用户,ALL:全体用户)*/ |
106 | - public static final String MSG_TYPE_UESR = "USER"; | ||
107 | - public static final String MSG_TYPE_ALL = "ALL"; | 106 | + String MSG_TYPE_UESR = "USER"; |
107 | + String MSG_TYPE_ALL = "ALL"; | ||
108 | 108 | ||
109 | /**发布状态(0未发布,1已发布,2已撤销)*/ | 109 | /**发布状态(0未发布,1已发布,2已撤销)*/ |
110 | - public static final String NO_SEND = "0"; | ||
111 | - public static final String HAS_SEND = "1"; | ||
112 | - public static final String HAS_CANCLE = "2"; | 110 | + String NO_SEND = "0"; |
111 | + String HAS_SEND = "1"; | ||
112 | + String HAS_CANCLE = "2"; | ||
113 | 113 | ||
114 | /**阅读状态(0未读,1已读)*/ | 114 | /**阅读状态(0未读,1已读)*/ |
115 | - public static final String HAS_READ_FLAG = "1"; | ||
116 | - public static final String NO_READ_FLAG = "0"; | 115 | + String HAS_READ_FLAG = "1"; |
116 | + String NO_READ_FLAG = "0"; | ||
117 | 117 | ||
118 | /**优先级(L低,M中,H高)*/ | 118 | /**优先级(L低,M中,H高)*/ |
119 | - public static final String PRIORITY_L = "L"; | ||
120 | - public static final String PRIORITY_M = "M"; | ||
121 | - public static final String PRIORITY_H = "H"; | 119 | + String PRIORITY_L = "L"; |
120 | + String PRIORITY_M = "M"; | ||
121 | + String PRIORITY_H = "H"; | ||
122 | 122 | ||
123 | /** | 123 | /** |
124 | * 短信模板方式 0 .登录模板、1.注册模板、2.忘记密码模板 | 124 | * 短信模板方式 0 .登录模板、1.注册模板、2.忘记密码模板 |
125 | */ | 125 | */ |
126 | - public static final String SMS_TPL_TYPE_0 = "0"; | ||
127 | - public static final String SMS_TPL_TYPE_1 = "1"; | ||
128 | - public static final String SMS_TPL_TYPE_2 = "2"; | 126 | + String SMS_TPL_TYPE_0 = "0"; |
127 | + String SMS_TPL_TYPE_1 = "1"; | ||
128 | + String SMS_TPL_TYPE_2 = "2"; | ||
129 | 129 | ||
130 | /** | 130 | /** |
131 | * 状态(0无效1有效) | 131 | * 状态(0无效1有效) |
132 | */ | 132 | */ |
133 | - public static final String STATUS_0 = "0"; | ||
134 | - public static final String STATUS_1 = "1"; | 133 | + String STATUS_0 = "0"; |
134 | + String STATUS_1 = "1"; | ||
135 | 135 | ||
136 | /** | 136 | /** |
137 | * 同步工作流引擎1同步0不同步 | 137 | * 同步工作流引擎1同步0不同步 |
138 | */ | 138 | */ |
139 | - public static final Integer ACT_SYNC_1 = 1; | ||
140 | - public static final Integer ACT_SYNC_0 = 0; | 139 | + Integer ACT_SYNC_1 = 1; |
140 | + Integer ACT_SYNC_0 = 0; | ||
141 | 141 | ||
142 | /** | 142 | /** |
143 | * 消息类型1:通知公告2:系统消息 | 143 | * 消息类型1:通知公告2:系统消息 |
144 | */ | 144 | */ |
145 | - public static final String MSG_CATEGORY_1 = "1"; | ||
146 | - public static final String MSG_CATEGORY_2 = "2"; | 145 | + String MSG_CATEGORY_1 = "1"; |
146 | + String MSG_CATEGORY_2 = "2"; | ||
147 | 147 | ||
148 | /** | 148 | /** |
149 | * 是否配置菜单的数据权限 1是0否 | 149 | * 是否配置菜单的数据权限 1是0否 |
150 | */ | 150 | */ |
151 | - public static final Integer RULE_FLAG_0 = 0; | ||
152 | - public static final Integer RULE_FLAG_1 = 1; | 151 | + Integer RULE_FLAG_0 = 0; |
152 | + Integer RULE_FLAG_1 = 1; | ||
153 | 153 | ||
154 | /** | 154 | /** |
155 | * 是否用户已被冻结 1正常(解冻) 2冻结 | 155 | * 是否用户已被冻结 1正常(解冻) 2冻结 |
156 | */ | 156 | */ |
157 | - public static final Integer USER_UNFREEZE = 1; | ||
158 | - public static final Integer USER_FREEZE = 2; | 157 | + Integer USER_UNFREEZE = 1; |
158 | + Integer USER_FREEZE = 2; | ||
159 | 159 | ||
160 | /**字典翻译文本后缀*/ | 160 | /**字典翻译文本后缀*/ |
161 | - public static final String DICT_TEXT_SUFFIX = "_dictText"; | 161 | + String DICT_TEXT_SUFFIX = "_dictText"; |
162 | 162 | ||
163 | /** | 163 | /** |
164 | * 表单设计器主表类型 | 164 | * 表单设计器主表类型 |
165 | */ | 165 | */ |
166 | - public static final Integer DESIGN_FORM_TYPE_MAIN = 1; | 166 | + Integer DESIGN_FORM_TYPE_MAIN = 1; |
167 | 167 | ||
168 | /** | 168 | /** |
169 | * 表单设计器子表表类型 | 169 | * 表单设计器子表表类型 |
170 | */ | 170 | */ |
171 | - public static final Integer DESIGN_FORM_TYPE_SUB = 2; | 171 | + Integer DESIGN_FORM_TYPE_SUB = 2; |
172 | 172 | ||
173 | /** | 173 | /** |
174 | * 表单设计器URL授权通过 | 174 | * 表单设计器URL授权通过 |
175 | */ | 175 | */ |
176 | - public static final Integer DESIGN_FORM_URL_STATUS_PASSED = 1; | 176 | + Integer DESIGN_FORM_URL_STATUS_PASSED = 1; |
177 | 177 | ||
178 | /** | 178 | /** |
179 | * 表单设计器URL授权未通过 | 179 | * 表单设计器URL授权未通过 |
180 | */ | 180 | */ |
181 | - public static final Integer DESIGN_FORM_URL_STATUS_NOT_PASSED = 2; | 181 | + Integer DESIGN_FORM_URL_STATUS_NOT_PASSED = 2; |
182 | 182 | ||
183 | /** | 183 | /** |
184 | * 表单设计器新增 Flag | 184 | * 表单设计器新增 Flag |
185 | */ | 185 | */ |
186 | - public static final String DESIGN_FORM_URL_TYPE_ADD = "add"; | 186 | + String DESIGN_FORM_URL_TYPE_ADD = "add"; |
187 | /** | 187 | /** |
188 | * 表单设计器修改 Flag | 188 | * 表单设计器修改 Flag |
189 | */ | 189 | */ |
190 | - public static final String DESIGN_FORM_URL_TYPE_EDIT = "edit"; | 190 | + String DESIGN_FORM_URL_TYPE_EDIT = "edit"; |
191 | /** | 191 | /** |
192 | * 表单设计器详情 Flag | 192 | * 表单设计器详情 Flag |
193 | */ | 193 | */ |
194 | - public static final String DESIGN_FORM_URL_TYPE_DETAIL = "detail"; | 194 | + String DESIGN_FORM_URL_TYPE_DETAIL = "detail"; |
195 | /** | 195 | /** |
196 | * 表单设计器复用数据 Flag | 196 | * 表单设计器复用数据 Flag |
197 | */ | 197 | */ |
198 | - public static final String DESIGN_FORM_URL_TYPE_REUSE = "reuse"; | 198 | + String DESIGN_FORM_URL_TYPE_REUSE = "reuse"; |
199 | /** | 199 | /** |
200 | * 表单设计器编辑 Flag (已弃用) | 200 | * 表单设计器编辑 Flag (已弃用) |
201 | */ | 201 | */ |
202 | - public static final String DESIGN_FORM_URL_TYPE_VIEW = "view"; | 202 | + String DESIGN_FORM_URL_TYPE_VIEW = "view"; |
203 | 203 | ||
204 | /** | 204 | /** |
205 | * online参数值设置(是:Y, 否:N) | 205 | * online参数值设置(是:Y, 否:N) |
206 | */ | 206 | */ |
207 | - public static final String ONLINE_PARAM_VAL_IS_TURE = "Y"; | ||
208 | - public static final String ONLINE_PARAM_VAL_IS_FALSE = "N"; | 207 | + String ONLINE_PARAM_VAL_IS_TURE = "Y"; |
208 | + String ONLINE_PARAM_VAL_IS_FALSE = "N"; | ||
209 | 209 | ||
210 | /** | 210 | /** |
211 | * 文件上传类型(本地:local,Minio:minio,阿里云:alioss) | 211 | * 文件上传类型(本地:local,Minio:minio,阿里云:alioss) |
212 | */ | 212 | */ |
213 | - public static final String UPLOAD_TYPE_LOCAL = "local"; | ||
214 | - public static final String UPLOAD_TYPE_MINIO = "minio"; | ||
215 | - public static final String UPLOAD_TYPE_OSS = "alioss"; | 213 | + String UPLOAD_TYPE_LOCAL = "local"; |
214 | + String UPLOAD_TYPE_MINIO = "minio"; | ||
215 | + String UPLOAD_TYPE_OSS = "alioss"; | ||
216 | 216 | ||
217 | /** | 217 | /** |
218 | * 文档上传自定义桶名称 | 218 | * 文档上传自定义桶名称 |
219 | */ | 219 | */ |
220 | - public static final String UPLOAD_CUSTOM_BUCKET = "eoafile"; | 220 | + String UPLOAD_CUSTOM_BUCKET = "eoafile"; |
221 | /** | 221 | /** |
222 | * 文档上传自定义路径 | 222 | * 文档上传自定义路径 |
223 | */ | 223 | */ |
224 | - public static final String UPLOAD_CUSTOM_PATH = "eoafile"; | 224 | + String UPLOAD_CUSTOM_PATH = "eoafile"; |
225 | /** | 225 | /** |
226 | * 文件外链接有效天数 | 226 | * 文件外链接有效天数 |
227 | */ | 227 | */ |
228 | - public static final Integer UPLOAD_EFFECTIVE_DAYS = 1; | 228 | + Integer UPLOAD_EFFECTIVE_DAYS = 1; |
229 | 229 | ||
230 | /** | 230 | /** |
231 | * 员工身份 (1:普通员工 2:上级) | 231 | * 员工身份 (1:普通员工 2:上级) |
232 | */ | 232 | */ |
233 | - public static final Integer USER_IDENTITY_1 = 1; | ||
234 | - public static final Integer USER_IDENTITY_2 = 2; | 233 | + Integer USER_IDENTITY_1 = 1; |
234 | + Integer USER_IDENTITY_2 = 2; | ||
235 | 235 | ||
236 | /** sys_user 表 username 唯一键索引 */ | 236 | /** sys_user 表 username 唯一键索引 */ |
237 | - public static final String SQL_INDEX_UNIQ_SYS_USER_USERNAME = "uniq_sys_user_username"; | 237 | + String SQL_INDEX_UNIQ_SYS_USER_USERNAME = "uniq_sys_user_username"; |
238 | /** sys_user 表 work_no 唯一键索引 */ | 238 | /** sys_user 表 work_no 唯一键索引 */ |
239 | - public static final String SQL_INDEX_UNIQ_SYS_USER_WORK_NO = "uniq_sys_user_work_no"; | 239 | + String SQL_INDEX_UNIQ_SYS_USER_WORK_NO = "uniq_sys_user_work_no"; |
240 | /** sys_user 表 phone 唯一键索引 */ | 240 | /** sys_user 表 phone 唯一键索引 */ |
241 | - public static final String SQL_INDEX_UNIQ_SYS_USER_PHONE = "uniq_sys_user_phone"; | 241 | + String SQL_INDEX_UNIQ_SYS_USER_PHONE = "uniq_sys_user_phone"; |
242 | /** 达梦数据库升提示。违反表[SYS_USER]唯一性约束 */ | 242 | /** 达梦数据库升提示。违反表[SYS_USER]唯一性约束 */ |
243 | - public static final String SQL_INDEX_UNIQ_SYS_USER = "唯一性约束"; | 243 | + String SQL_INDEX_UNIQ_SYS_USER = "唯一性约束"; |
244 | 244 | ||
245 | /** sys_user 表 email 唯一键索引 */ | 245 | /** sys_user 表 email 唯一键索引 */ |
246 | - public static final String SQL_INDEX_UNIQ_SYS_USER_EMAIL = "uniq_sys_user_email"; | 246 | + String SQL_INDEX_UNIQ_SYS_USER_EMAIL = "uniq_sys_user_email"; |
247 | /** sys_quartz_job 表 job_class_name 唯一键索引 */ | 247 | /** sys_quartz_job 表 job_class_name 唯一键索引 */ |
248 | - public static final String SQL_INDEX_UNIQ_JOB_CLASS_NAME = "uniq_job_class_name"; | 248 | + String SQL_INDEX_UNIQ_JOB_CLASS_NAME = "uniq_job_class_name"; |
249 | /** sys_position 表 code 唯一键索引 */ | 249 | /** sys_position 表 code 唯一键索引 */ |
250 | - public static final String SQL_INDEX_UNIQ_CODE = "uniq_code"; | 250 | + String SQL_INDEX_UNIQ_CODE = "uniq_code"; |
251 | /** sys_role 表 code 唯一键索引 */ | 251 | /** sys_role 表 code 唯一键索引 */ |
252 | - public static final String SQL_INDEX_UNIQ_SYS_ROLE_CODE = "uniq_sys_role_role_code"; | 252 | + String SQL_INDEX_UNIQ_SYS_ROLE_CODE = "uniq_sys_role_role_code"; |
253 | /** sys_depart 表 code 唯一键索引 */ | 253 | /** sys_depart 表 code 唯一键索引 */ |
254 | - public static final String SQL_INDEX_UNIQ_DEPART_ORG_CODE = "uniq_depart_org_code"; | 254 | + String SQL_INDEX_UNIQ_DEPART_ORG_CODE = "uniq_depart_org_code"; |
255 | /** sys_category 表 code 唯一键索引 */ | 255 | /** sys_category 表 code 唯一键索引 */ |
256 | - public static final String SQL_INDEX_UNIQ_CATEGORY_CODE = "idx_sc_code"; | 256 | + String SQL_INDEX_UNIQ_CATEGORY_CODE = "idx_sc_code"; |
257 | /** | 257 | /** |
258 | * 在线聊天 是否为默认分组 | 258 | * 在线聊天 是否为默认分组 |
259 | */ | 259 | */ |
260 | - public static final String IM_DEFAULT_GROUP = "1"; | 260 | + String IM_DEFAULT_GROUP = "1"; |
261 | /** | 261 | /** |
262 | * 在线聊天 图片文件保存路径 | 262 | * 在线聊天 图片文件保存路径 |
263 | */ | 263 | */ |
264 | - public static final String IM_UPLOAD_CUSTOM_PATH = "imfile"; | 264 | + String IM_UPLOAD_CUSTOM_PATH = "imfile"; |
265 | /** | 265 | /** |
266 | * 在线聊天 用户状态 | 266 | * 在线聊天 用户状态 |
267 | */ | 267 | */ |
268 | - public static final String IM_STATUS_ONLINE = "online"; | 268 | + String IM_STATUS_ONLINE = "online"; |
269 | 269 | ||
270 | /** | 270 | /** |
271 | * 在线聊天 SOCKET消息类型 | 271 | * 在线聊天 SOCKET消息类型 |
272 | */ | 272 | */ |
273 | - public static final String IM_SOCKET_TYPE = "chatMessage"; | 273 | + String IM_SOCKET_TYPE = "chatMessage"; |
274 | 274 | ||
275 | /** | 275 | /** |
276 | * 在线聊天 是否开启默认添加好友 1是 0否 | 276 | * 在线聊天 是否开启默认添加好友 1是 0否 |
277 | */ | 277 | */ |
278 | - public static final String IM_DEFAULT_ADD_FRIEND = "1"; | 278 | + String IM_DEFAULT_ADD_FRIEND = "1"; |
279 | 279 | ||
280 | /** | 280 | /** |
281 | * 在线聊天 用户好友缓存前缀 | 281 | * 在线聊天 用户好友缓存前缀 |
282 | */ | 282 | */ |
283 | - public static final String IM_PREFIX_USER_FRIEND_CACHE = "sys:cache:im:im_prefix_user_friend_"; | 283 | + String IM_PREFIX_USER_FRIEND_CACHE = "sys:cache:im:im_prefix_user_friend_"; |
284 | 284 | ||
285 | /** | 285 | /** |
286 | * 考勤补卡业务状态 (1:同意 2:不同意) | 286 | * 考勤补卡业务状态 (1:同意 2:不同意) |
287 | */ | 287 | */ |
288 | - public static final String SIGN_PATCH_BIZ_STATUS_1 = "1"; | ||
289 | - public static final String SIGN_PATCH_BIZ_STATUS_2 = "2"; | 288 | + String SIGN_PATCH_BIZ_STATUS_1 = "1"; |
289 | + String SIGN_PATCH_BIZ_STATUS_2 = "2"; | ||
290 | 290 | ||
291 | /** | 291 | /** |
292 | * 公文文档上传自定义路径 | 292 | * 公文文档上传自定义路径 |
293 | */ | 293 | */ |
294 | - public static final String UPLOAD_CUSTOM_PATH_OFFICIAL = "officialdoc"; | 294 | + String UPLOAD_CUSTOM_PATH_OFFICIAL = "officialdoc"; |
295 | /** | 295 | /** |
296 | * 公文文档下载自定义路径 | 296 | * 公文文档下载自定义路径 |
297 | */ | 297 | */ |
298 | - public static final String DOWNLOAD_CUSTOM_PATH_OFFICIAL = "officaldown"; | 298 | + String DOWNLOAD_CUSTOM_PATH_OFFICIAL = "officaldown"; |
299 | 299 | ||
300 | /** | 300 | /** |
301 | * WPS存储值类别(1 code文号 2 text(WPS模板还是公文发文模板)) | 301 | * WPS存储值类别(1 code文号 2 text(WPS模板还是公文发文模板)) |
302 | */ | 302 | */ |
303 | - public static final String WPS_TYPE_1="1"; | ||
304 | - public static final String WPS_TYPE_2="2"; | 303 | + String WPS_TYPE_1="1"; |
304 | + String WPS_TYPE_2="2"; | ||
305 | 305 | ||
306 | 306 | ||
307 | - public final static String X_ACCESS_TOKEN = "X-Access-Token"; | ||
308 | - public final static String X_SIGN = "X-Sign"; | ||
309 | - public final static String X_TIMESTAMP = "X-TIMESTAMP"; | ||
310 | - public final static String TOKEN_IS_INVALID_MSG = "Token失效,请重新登录!"; | 307 | + String X_ACCESS_TOKEN = "X-Access-Token"; |
308 | + String X_SIGN = "X-Sign"; | ||
309 | + String X_TIMESTAMP = "X-TIMESTAMP"; | ||
310 | + String TOKEN_IS_INVALID_MSG = "Token失效,请重新登录!"; | ||
311 | + String X_FORWARDED_SCHEME = "X-Forwarded-Scheme"; | ||
311 | 312 | ||
312 | /** | 313 | /** |
313 | * 多租户 请求头 | 314 | * 多租户 请求头 |
314 | */ | 315 | */ |
315 | - public final static String TENANT_ID = "tenant-id"; | 316 | + String TENANT_ID = "tenant-id"; |
316 | 317 | ||
317 | /** | 318 | /** |
318 | * 微服务读取配置文件属性 服务地址 | 319 | * 微服务读取配置文件属性 服务地址 |
319 | */ | 320 | */ |
320 | - public final static String CLOUD_SERVER_KEY = "spring.cloud.nacos.discovery.server-addr"; | 321 | + String CLOUD_SERVER_KEY = "spring.cloud.nacos.discovery.server-addr"; |
321 | 322 | ||
322 | /** | 323 | /** |
323 | * 第三方登录 验证密码/创建用户 都需要设置一个操作码 防止被恶意调用 | 324 | * 第三方登录 验证密码/创建用户 都需要设置一个操作码 防止被恶意调用 |
324 | */ | 325 | */ |
325 | - public final static String THIRD_LOGIN_CODE = "third_login_code"; | 326 | + String THIRD_LOGIN_CODE = "third_login_code"; |
326 | 327 | ||
327 | /** | 328 | /** |
328 | * 第三方APP同步方向:本地 --> 第三方APP | 329 | * 第三方APP同步方向:本地 --> 第三方APP |
@@ -361,16 +362,43 @@ public interface CommonConstant { | @@ -361,16 +362,43 @@ public interface CommonConstant { | ||
361 | /**String 类型的空值*/ | 362 | /**String 类型的空值*/ |
362 | String STRING_NULL = "null"; | 363 | String STRING_NULL = "null"; |
363 | 364 | ||
364 | - /**java.util.Date 包*/ | ||
365 | - String JAVA_UTIL_DATE = "java.util.Date"; | 365 | + /**前端vue3版本Header参数名*/ |
366 | + String VERSION="X-Version"; | ||
366 | 367 | ||
367 | - /**.do*/ | ||
368 | - String SPOT_DO = ".do"; | 368 | + /**存储在线程变量里的动态表名*/ |
369 | + String DYNAMIC_TABLE_NAME="DYNAMIC_TABLE_NAME"; | ||
370 | + /** | ||
371 | + * http:// http协议 | ||
372 | + */ | ||
373 | + String HTTP_PROTOCOL = "http://"; | ||
369 | 374 | ||
375 | + /** | ||
376 | + * https:// https协议 | ||
377 | + */ | ||
378 | + String HTTPS_PROTOCOL = "https://"; | ||
379 | + | ||
380 | + /** 部门表唯一key,id */ | ||
381 | + String DEPART_KEY_ID = "id"; | ||
382 | + /** 部门表唯一key,orgCode */ | ||
383 | + String DEPART_KEY_ORG_CODE = "orgCode"; | ||
370 | 384 | ||
371 | - /**前端vue版本标识*/ | ||
372 | - String VERSION="X-Version"; | 385 | + /** |
386 | + * 发消息 会传递一些信息到map | ||
387 | + */ | ||
388 | + String NOTICE_MSG_SUMMARY = "NOTICE_MSG_SUMMARY"; | ||
373 | 389 | ||
374 | - /**前端vue版本*/ | ||
375 | - String VERSION_VUE3="vue3"; | 390 | + /** |
391 | + * 发消息 会传递一个业务ID到map | ||
392 | + */ | ||
393 | + String NOTICE_MSG_BUS_ID = "NOTICE_MSG_BUS_ID"; | ||
394 | + | ||
395 | + /** | ||
396 | + * 邮箱消息中地址登录时地址后携带的token,需要替换成真实的token值 | ||
397 | + */ | ||
398 | + String LOGIN_TOKEN = "{LOGIN_TOKEN}"; | ||
399 | + | ||
400 | + /** | ||
401 | + * 模板消息中 跳转地址的对应的key | ||
402 | + */ | ||
403 | + String MSG_HREF_URL = "url"; | ||
376 | } | 404 | } |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/DataBaseConstant.java
@@ -153,4 +153,14 @@ public interface DataBaseConstant { | @@ -153,4 +153,14 @@ public interface DataBaseConstant { | ||
153 | * sql语句 where | 153 | * sql语句 where |
154 | */ | 154 | */ |
155 | String SQL_WHERE = "where"; | 155 | String SQL_WHERE = "where"; |
156 | + | ||
157 | + /** | ||
158 | + * sql语句 asc | ||
159 | + */ | ||
160 | + String SQL_ASC = "asc"; | ||
161 | + | ||
162 | + /** | ||
163 | + * sqlserver数据库,中间有空格 | ||
164 | + */ | ||
165 | + String DB_TYPE_SQL_SERVER_BLANK = "sql server"; | ||
156 | } | 166 | } |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/DynamicTableConstant.java
0 → 100644
1 | +package org.jeecg.common.constant; | ||
2 | + | ||
3 | +/** | ||
4 | + * 动态切换表配置常量 | ||
5 | + * | ||
6 | + * @author: scott | ||
7 | + * @date: 2022年04月25日 22:30 | ||
8 | + */ | ||
9 | +public class DynamicTableConstant { | ||
10 | + /** | ||
11 | + * 角色首页配置表 | ||
12 | + * vue2表名: sys_role_index | ||
13 | + * vue3表名: sys_role_index_vue3 | ||
14 | + */ | ||
15 | + public static final String SYS_ROLE_INDEX = "sys_role_index"; | ||
16 | +} |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/ProvinceCityArea.java
@@ -35,9 +35,13 @@ public class ProvinceCityArea { | @@ -35,9 +35,13 @@ public class ProvinceCityArea { | ||
35 | this.initAreaList(); | 35 | this.initAreaList(); |
36 | if(areaList!=null && areaList.size()>0){ | 36 | if(areaList!=null && areaList.size()>0){ |
37 | for(int i=areaList.size()-1;i>=0;i--){ | 37 | for(int i=areaList.size()-1;i>=0;i--){ |
38 | - if(text.indexOf(areaList.get(i).getText())>=0){ | 38 | + //update-begin-author:taoyan date:2022-5-24 for:VUEN-1088 online 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区 |
39 | + String areaText = areaList.get(i).getText(); | ||
40 | + String cityText = areaList.get(i).getAheadText(); | ||
41 | + if(text.indexOf(areaText)>=0 && (cityText!=null && text.indexOf(cityText)>=0)){ | ||
39 | return areaList.get(i).getId(); | 42 | return areaList.get(i).getId(); |
40 | } | 43 | } |
44 | + //update-end-author:taoyan date:2022-5-24 for:VUEN-1088 online 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区 | ||
41 | } | 45 | } |
42 | } | 46 | } |
43 | return null; | 47 | return null; |
@@ -145,6 +149,9 @@ public class ProvinceCityArea { | @@ -145,6 +149,9 @@ public class ProvinceCityArea { | ||
145 | for(String areaKey:areaJson.keySet()){ | 149 | for(String areaKey:areaJson.keySet()){ |
146 | //System.out.println("········"+areaKey); | 150 | //System.out.println("········"+areaKey); |
147 | Area area = new Area(areaKey,areaJson.getString(areaKey),cityKey); | 151 | Area area = new Area(areaKey,areaJson.getString(areaKey),cityKey); |
152 | + //update-begin-author:taoyan date:2022-5-24 for:VUEN-1088 online 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区 | ||
153 | + area.setAheadText(cityJson.getString(cityKey)); | ||
154 | + //update-end-author:taoyan date:2022-5-24 for:VUEN-1088 online 导入 省市区导入后 导入数据错乱 北京市/市辖区/西城区-->山西省/晋城市/城区 | ||
148 | this.areaList.add(area); | 155 | this.areaList.add(area); |
149 | } | 156 | } |
150 | } | 157 | } |
@@ -180,6 +187,8 @@ public class ProvinceCityArea { | @@ -180,6 +187,8 @@ public class ProvinceCityArea { | ||
180 | String id; | 187 | String id; |
181 | String text; | 188 | String text; |
182 | String pid; | 189 | String pid; |
190 | + // 用于存储上级文本数据,区的上级文本 是市的数据 | ||
191 | + String aheadText; | ||
183 | 192 | ||
184 | public Area(String id,String text,String pid){ | 193 | public Area(String id,String text,String pid){ |
185 | this.id = id; | 194 | this.id = id; |
@@ -198,5 +207,12 @@ public class ProvinceCityArea { | @@ -198,5 +207,12 @@ public class ProvinceCityArea { | ||
198 | public String getPid() { | 207 | public String getPid() { |
199 | return pid; | 208 | return pid; |
200 | } | 209 | } |
210 | + | ||
211 | + public String getAheadText() { | ||
212 | + return aheadText; | ||
213 | + } | ||
214 | + public void setAheadText(String aheadText) { | ||
215 | + this.aheadText = aheadText; | ||
216 | + } | ||
201 | } | 217 | } |
202 | } | 218 | } |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/SymbolConstant.java
@@ -86,4 +86,34 @@ public class SymbolConstant { | @@ -86,4 +86,34 @@ public class SymbolConstant { | ||
86 | * 符号:和 & | 86 | * 符号:和 & |
87 | */ | 87 | */ |
88 | public static final String AND = "&"; | 88 | public static final String AND = "&"; |
89 | + | ||
90 | + /** | ||
91 | + * 符号:../ | ||
92 | + */ | ||
93 | + public static final String SPOT_SINGLE_SLASH = "../"; | ||
94 | + | ||
95 | + /** | ||
96 | + * 符号:..\\ | ||
97 | + */ | ||
98 | + public static final String SPOT_DOUBLE_BACKSLASH = "..\\"; | ||
99 | + | ||
100 | + /** | ||
101 | + * 系统变量前缀 #{ | ||
102 | + */ | ||
103 | + public static final String SYS_VAR_PREFIX = "#{"; | ||
104 | + | ||
105 | + /** | ||
106 | + * 符号 {{ | ||
107 | + */ | ||
108 | + public static final String DOUBLE_LEFT_CURLY_BRACKET = "{{"; | ||
109 | + | ||
110 | + /** | ||
111 | + * 符号:[ | ||
112 | + */ | ||
113 | + public static final String SQUARE_BRACKETS_LEFT = "["; | ||
114 | + /** | ||
115 | + * 符号:] | ||
116 | + */ | ||
117 | + public static final String SQUARE_BRACKETS_RIGHT = "]"; | ||
118 | + | ||
89 | } | 119 | } |
90 | \ No newline at end of file | 120 | \ No newline at end of file |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/enums/CgformEnum.java
@@ -20,13 +20,14 @@ public enum CgformEnum { | @@ -20,13 +20,14 @@ public enum CgformEnum { | ||
20 | */ | 20 | */ |
21 | MANY(2, "many", "/jeecg/code-template-online", "default.onetomany", "经典风格"), | 21 | MANY(2, "many", "/jeecg/code-template-online", "default.onetomany", "经典风格"), |
22 | /** | 22 | /** |
23 | - * 多表 | ||
24 | - */ | ||
25 | - ERP(2, "erp", "/jeecg/code-template-online", "erp.onetomany", "ERP风格"), | ||
26 | - /** | ||
27 | * 多表(jvxe风格) | 23 | * 多表(jvxe风格) |
28 | * */ | 24 | * */ |
29 | JVXE_TABLE(2, "jvxe", "/jeecg/code-template-online", "jvxe.onetomany", "JVXE风格"), | 25 | JVXE_TABLE(2, "jvxe", "/jeecg/code-template-online", "jvxe.onetomany", "JVXE风格"), |
26 | + | ||
27 | + /** | ||
28 | + * 多表 | ||
29 | + */ | ||
30 | + ERP(2, "erp", "/jeecg/code-template-online", "erp.onetomany", "ERP风格"), | ||
30 | /** | 31 | /** |
31 | * 多表(内嵌子表风格) | 32 | * 多表(内嵌子表风格) |
32 | */ | 33 | */ |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/enums/LowAppAopEnum.java
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/constant/enums/MessageTypeEnum.java
0 → 100644
1 | +package org.jeecg.common.constant.enums; | ||
2 | + | ||
3 | +import org.jeecg.common.system.annotation.EnumDict; | ||
4 | +import org.jeecg.common.system.vo.DictModel; | ||
5 | + | ||
6 | +import java.util.ArrayList; | ||
7 | +import java.util.List; | ||
8 | + | ||
9 | +/** | ||
10 | + * 消息类型 | ||
11 | + * @author: jeecg-boot | ||
12 | + */ | ||
13 | +@EnumDict("messageType") | ||
14 | +public enum MessageTypeEnum { | ||
15 | + | ||
16 | + XT("system", "系统消息"), | ||
17 | + YJ("email", "邮件消息"), | ||
18 | + DD("dingtalk", "钉钉消息"), | ||
19 | + QYWX("wechat_enterprise", "企业微信"); | ||
20 | + | ||
21 | + MessageTypeEnum(String type, String note){ | ||
22 | + this.type = type; | ||
23 | + this.note = note; | ||
24 | + } | ||
25 | + | ||
26 | + /** | ||
27 | + * 消息类型 | ||
28 | + */ | ||
29 | + String type; | ||
30 | + | ||
31 | + /** | ||
32 | + * 类型说明 | ||
33 | + */ | ||
34 | + String note; | ||
35 | + | ||
36 | + public String getNote() { | ||
37 | + return note; | ||
38 | + } | ||
39 | + | ||
40 | + public void setNote(String note) { | ||
41 | + this.note = note; | ||
42 | + } | ||
43 | + | ||
44 | + public String getType() { | ||
45 | + return type; | ||
46 | + } | ||
47 | + | ||
48 | + public void setType(String type) { | ||
49 | + this.type = type; | ||
50 | + } | ||
51 | + | ||
52 | + | ||
53 | + /** | ||
54 | + * 获取字典数据 | ||
55 | + * @return | ||
56 | + */ | ||
57 | + public static List<DictModel> getDictList(){ | ||
58 | + List<DictModel> list = new ArrayList<>(); | ||
59 | + DictModel dictModel = null; | ||
60 | + for(MessageTypeEnum e: MessageTypeEnum.values()){ | ||
61 | + dictModel = new DictModel(); | ||
62 | + dictModel.setValue(e.getType()); | ||
63 | + dictModel.setText(e.getNote()); | ||
64 | + list.add(dictModel); | ||
65 | + } | ||
66 | + return list; | ||
67 | + } | ||
68 | +} |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/exception/JeecgBootExceptionHandler.java
@@ -123,7 +123,8 @@ public class JeecgBootExceptionHandler { | @@ -123,7 +123,8 @@ public class JeecgBootExceptionHandler { | ||
123 | @ExceptionHandler(DataIntegrityViolationException.class) | 123 | @ExceptionHandler(DataIntegrityViolationException.class) |
124 | public Result<?> handleDataIntegrityViolationException(DataIntegrityViolationException e) { | 124 | public Result<?> handleDataIntegrityViolationException(DataIntegrityViolationException e) { |
125 | log.error(e.getMessage(), e); | 125 | log.error(e.getMessage(), e); |
126 | - return Result.error("字段太长,超出数据库字段的长度"); | 126 | + //【issues/3624】数据库执行异常handleDataIntegrityViolationException提示有误 #3624 |
127 | + return Result.error("执行数据库异常,违反了完整性例如:违反惟一约束、违反非空限制、字段内容超出长度等"); | ||
127 | } | 128 | } |
128 | 129 | ||
129 | @ExceptionHandler(PoolException.class) | 130 | @ExceptionHandler(PoolException.class) |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/annotation/EnumDict.java
0 → 100644
1 | +package org.jeecg.common.system.annotation; | ||
2 | + | ||
3 | +import java.lang.annotation.*; | ||
4 | + | ||
5 | +/** | ||
6 | + * 将枚举类转化成字典数据 | ||
7 | + * @Author taoYan | ||
8 | + * @Date 2022/7/8 10:34 | ||
9 | + **/ | ||
10 | +@Target(ElementType.TYPE) | ||
11 | +@Retention(RetentionPolicy.RUNTIME) | ||
12 | +@Documented | ||
13 | +public @interface EnumDict { | ||
14 | + | ||
15 | + /** | ||
16 | + * 作为字典数据的唯一编码 | ||
17 | + */ | ||
18 | + String value() default ""; | ||
19 | +} |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/base/controller/JeecgController.java
@@ -53,18 +53,14 @@ public class JeecgController<T, S extends IService<T>> { | @@ -53,18 +53,14 @@ public class JeecgController<T, S extends IService<T>> { | ||
53 | QueryWrapper<T> queryWrapper = QueryGenerator.initQueryWrapper(object, request.getParameterMap()); | 53 | QueryWrapper<T> queryWrapper = QueryGenerator.initQueryWrapper(object, request.getParameterMap()); |
54 | LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); | 54 | LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal(); |
55 | 55 | ||
56 | - // Step.2 获取导出数据 | ||
57 | - List<T> pageList = service.list(queryWrapper); | ||
58 | - List<T> exportList = null; | ||
59 | - | ||
60 | // 过滤选中数据 | 56 | // 过滤选中数据 |
61 | String selections = request.getParameter("selections"); | 57 | String selections = request.getParameter("selections"); |
62 | if (oConvertUtils.isNotEmpty(selections)) { | 58 | if (oConvertUtils.isNotEmpty(selections)) { |
63 | List<String> selectionList = Arrays.asList(selections.split(",")); | 59 | List<String> selectionList = Arrays.asList(selections.split(",")); |
64 | - exportList = pageList.stream().filter(item -> selectionList.contains(getId(item))).collect(Collectors.toList()); | ||
65 | - } else { | ||
66 | - exportList = pageList; | 60 | + queryWrapper.in("id",selectionList); |
67 | } | 61 | } |
62 | + // Step.2 获取导出数据 | ||
63 | + List<T> exportList = service.list(queryWrapper); | ||
68 | 64 | ||
69 | // Step.3 AutoPoi 导出Excel | 65 | // Step.3 AutoPoi 导出Excel |
70 | ModelAndView mv = new ModelAndView(new JeecgEntityExcelView()); | 66 | ModelAndView mv = new ModelAndView(new JeecgEntityExcelView()); |
@@ -97,21 +93,20 @@ public class JeecgController<T, S extends IService<T>> { | @@ -97,21 +93,20 @@ public class JeecgController<T, S extends IService<T>> { | ||
97 | // Step.2 计算分页sheet数据 | 93 | // Step.2 计算分页sheet数据 |
98 | double total = service.count(); | 94 | double total = service.count(); |
99 | int count = (int)Math.ceil(total/pageNum); | 95 | int count = (int)Math.ceil(total/pageNum); |
100 | - // Step.3 多sheet处理 | 96 | + //update-begin-author:liusq---date:20220629--for: 多sheet导出根据选择导出写法调整 --- |
97 | + // Step.3 过滤选中数据 | ||
98 | + String selections = request.getParameter("selections"); | ||
99 | + if (oConvertUtils.isNotEmpty(selections)) { | ||
100 | + List<String> selectionList = Arrays.asList(selections.split(",")); | ||
101 | + queryWrapper.in("id",selectionList); | ||
102 | + } | ||
103 | + //update-end-author:liusq---date:20220629--for: 多sheet导出根据选择导出写法调整 --- | ||
104 | + // Step.4 多sheet处理 | ||
101 | List<Map<String, Object>> listMap = new ArrayList<Map<String, Object>>(); | 105 | List<Map<String, Object>> listMap = new ArrayList<Map<String, Object>>(); |
102 | for (int i = 1; i <=count ; i++) { | 106 | for (int i = 1; i <=count ; i++) { |
103 | Page<T> page = new Page<T>(i, pageNum); | 107 | Page<T> page = new Page<T>(i, pageNum); |
104 | IPage<T> pageList = service.page(page, queryWrapper); | 108 | IPage<T> pageList = service.page(page, queryWrapper); |
105 | - List<T> records = pageList.getRecords(); | ||
106 | - List<T> exportList = null; | ||
107 | - // 过滤选中数据 | ||
108 | - String selections = request.getParameter("selections"); | ||
109 | - if (oConvertUtils.isNotEmpty(selections)) { | ||
110 | - List<String> selectionList = Arrays.asList(selections.split(",")); | ||
111 | - exportList = records.stream().filter(item -> selectionList.contains(getId(item))).collect(Collectors.toList()); | ||
112 | - } else { | ||
113 | - exportList = records; | ||
114 | - } | 109 | + List<T> exportList = pageList.getRecords(); |
115 | Map<String, Object> map = new HashMap<>(5); | 110 | Map<String, Object> map = new HashMap<>(5); |
116 | ExportParams exportParams=new ExportParams(title + "报表", "导出人:" + sysUser.getRealname(), title+i,upLoadPath); | 111 | ExportParams exportParams=new ExportParams(title + "报表", "导出人:" + sysUser.getRealname(), title+i,upLoadPath); |
117 | exportParams.setType(ExcelType.XSSF); | 112 | exportParams.setType(ExcelType.XSSF); |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/query/QueryGenerator.java
@@ -16,6 +16,7 @@ import org.apache.commons.beanutils.PropertyUtils; | @@ -16,6 +16,7 @@ import org.apache.commons.beanutils.PropertyUtils; | ||
16 | import org.jeecg.common.constant.CommonConstant; | 16 | import org.jeecg.common.constant.CommonConstant; |
17 | import org.jeecg.common.constant.DataBaseConstant; | 17 | import org.jeecg.common.constant.DataBaseConstant; |
18 | import org.jeecg.common.constant.SymbolConstant; | 18 | import org.jeecg.common.constant.SymbolConstant; |
19 | +import org.jeecg.common.exception.JeecgBootException; | ||
19 | import org.jeecg.common.system.util.JeecgDataAutorUtils; | 20 | import org.jeecg.common.system.util.JeecgDataAutorUtils; |
20 | import org.jeecg.common.system.util.JwtUtil; | 21 | import org.jeecg.common.system.util.JwtUtil; |
21 | import org.jeecg.common.system.vo.SysPermissionDataRuleModel; | 22 | import org.jeecg.common.system.vo.SysPermissionDataRuleModel; |
@@ -191,8 +192,8 @@ public class QueryGenerator { | @@ -191,8 +192,8 @@ public class QueryGenerator { | ||
191 | log.error(e.getMessage(), e); | 192 | log.error(e.getMessage(), e); |
192 | } | 193 | } |
193 | } | 194 | } |
194 | - // 排序逻辑 处理 | ||
195 | - doMultiFieldsOrder(queryWrapper, parameterMap); | 195 | + // 排序逻辑 处理 |
196 | + doMultiFieldsOrder(queryWrapper, parameterMap, fieldColumnMap.keySet()); | ||
196 | 197 | ||
197 | //高级查询 | 198 | //高级查询 |
198 | doSuperQuery(queryWrapper, parameterMap, fieldColumnMap); | 199 | doSuperQuery(queryWrapper, parameterMap, fieldColumnMap); |
@@ -228,8 +229,7 @@ public class QueryGenerator { | @@ -228,8 +229,7 @@ public class QueryGenerator { | ||
228 | } | 229 | } |
229 | } | 230 | } |
230 | 231 | ||
231 | - /**多字段排序 TODO 需要修改前端*/ | ||
232 | - private static void doMultiFieldsOrder(QueryWrapper<?> queryWrapper,Map<String, String[]> parameterMap) { | 232 | + private static void doMultiFieldsOrder(QueryWrapper<?> queryWrapper,Map<String, String[]> parameterMap, Set<String> allFields) { |
233 | String column=null,order=null; | 233 | String column=null,order=null; |
234 | if(parameterMap!=null&& parameterMap.containsKey(ORDER_COLUMN)) { | 234 | if(parameterMap!=null&& parameterMap.containsKey(ORDER_COLUMN)) { |
235 | column = parameterMap.get(ORDER_COLUMN)[0]; | 235 | column = parameterMap.get(ORDER_COLUMN)[0]; |
@@ -243,6 +243,15 @@ public class QueryGenerator { | @@ -243,6 +243,15 @@ public class QueryGenerator { | ||
243 | if(column.endsWith(CommonConstant.DICT_TEXT_SUFFIX)) { | 243 | if(column.endsWith(CommonConstant.DICT_TEXT_SUFFIX)) { |
244 | column = column.substring(0, column.lastIndexOf(CommonConstant.DICT_TEXT_SUFFIX)); | 244 | column = column.substring(0, column.lastIndexOf(CommonConstant.DICT_TEXT_SUFFIX)); |
245 | } | 245 | } |
246 | + | ||
247 | + //update-begin-author:taoyan date:2022-5-16 for: issues/3676 获取系统用户列表时,使用SQL注入生效 | ||
248 | + //判断column是不是当前实体的 | ||
249 | + log.info("当前字段有:"+ allFields); | ||
250 | + if (!allColumnExist(column, allFields)) { | ||
251 | + throw new JeecgBootException("请注意,将要排序的列字段不存在:" + column); | ||
252 | + } | ||
253 | + //update-end-author:taoyan date:2022-5-16 for: issues/3676 获取系统用户列表时,使用SQL注入生效 | ||
254 | + | ||
246 | //SQL注入check | 255 | //SQL注入check |
247 | SqlInjectionUtil.filterContent(column); | 256 | SqlInjectionUtil.filterContent(column); |
248 | 257 | ||
@@ -264,6 +273,28 @@ public class QueryGenerator { | @@ -264,6 +273,28 @@ public class QueryGenerator { | ||
264 | //update-end--Author:scott Date:20210531 for:36 多条件排序无效问题修正------- | 273 | //update-end--Author:scott Date:20210531 for:36 多条件排序无效问题修正------- |
265 | } | 274 | } |
266 | } | 275 | } |
276 | + | ||
277 | + //update-begin-author:taoyan date:2022-5-23 for: issues/3676 获取系统用户列表时,使用SQL注入生效 | ||
278 | + /** | ||
279 | + * 多字段排序 判断所传字段是否存在 | ||
280 | + * @return | ||
281 | + */ | ||
282 | + private static boolean allColumnExist(String columnStr, Set<String> allFields){ | ||
283 | + boolean exist = true; | ||
284 | + if(columnStr.indexOf(COMMA)>=0){ | ||
285 | + String[] arr = columnStr.split(COMMA); | ||
286 | + for(String column: arr){ | ||
287 | + if(!allFields.contains(column)){ | ||
288 | + exist = false; | ||
289 | + break; | ||
290 | + } | ||
291 | + } | ||
292 | + }else{ | ||
293 | + exist = allFields.contains(columnStr); | ||
294 | + } | ||
295 | + return exist; | ||
296 | + } | ||
297 | + //update-end-author:taoyan date:2022-5-23 for: issues/3676 获取系统用户列表时,使用SQL注入生效 | ||
267 | 298 | ||
268 | /** | 299 | /** |
269 | * 高级查询 | 300 | * 高级查询 |
@@ -825,13 +856,13 @@ public class QueryGenerator { | @@ -825,13 +856,13 @@ public class QueryGenerator { | ||
825 | res = field + " in "+getInConditionValue(value, isString); | 856 | res = field + " in "+getInConditionValue(value, isString); |
826 | break; | 857 | break; |
827 | case LIKE: | 858 | case LIKE: |
828 | - res = field + " like "+getLikeConditionValue(value); | 859 | + res = field + " like "+getLikeConditionValue(value, QueryRuleEnum.LIKE); |
829 | break; | 860 | break; |
830 | case LEFT_LIKE: | 861 | case LEFT_LIKE: |
831 | - res = field + " like "+getLikeConditionValue(value); | 862 | + res = field + " like "+getLikeConditionValue(value, QueryRuleEnum.LEFT_LIKE); |
832 | break; | 863 | break; |
833 | case RIGHT_LIKE: | 864 | case RIGHT_LIKE: |
834 | - res = field + " like "+getLikeConditionValue(value); | 865 | + res = field + " like "+getLikeConditionValue(value, QueryRuleEnum.RIGHT_LIKE); |
835 | break; | 866 | break; |
836 | default: | 867 | default: |
837 | res = field+" = "+getFieldConditionValue(value, isString, dataBaseType); | 868 | res = field+" = "+getFieldConditionValue(value, isString, dataBaseType); |
@@ -914,8 +945,15 @@ public class QueryGenerator { | @@ -914,8 +945,15 @@ public class QueryGenerator { | ||
914 | } | 945 | } |
915 | //update-end-author:taoyan date:20210628 for: 查询条件如果输入,导致sql报错 | 946 | //update-end-author:taoyan date:20210628 for: 查询条件如果输入,导致sql报错 |
916 | } | 947 | } |
917 | - | ||
918 | - private static String getLikeConditionValue(Object value) { | 948 | + |
949 | + /** | ||
950 | + * 先根据值判断 走左模糊还是右模糊 | ||
951 | + * 最后如果值不带任何标识(*或者%),则再根据ruleEnum判断 | ||
952 | + * @param value | ||
953 | + * @param ruleEnum | ||
954 | + * @return | ||
955 | + */ | ||
956 | + private static String getLikeConditionValue(Object value, QueryRuleEnum ruleEnum) { | ||
919 | String str = value.toString().trim(); | 957 | String str = value.toString().trim(); |
920 | if(str.startsWith(SymbolConstant.ASTERISK) && str.endsWith(SymbolConstant.ASTERISK)) { | 958 | if(str.startsWith(SymbolConstant.ASTERISK) && str.endsWith(SymbolConstant.ASTERISK)) { |
921 | if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())){ | 959 | if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())){ |
@@ -951,11 +989,30 @@ public class QueryGenerator { | @@ -951,11 +989,30 @@ public class QueryGenerator { | ||
951 | } | 989 | } |
952 | } | 990 | } |
953 | }else { | 991 | }else { |
954 | - if(DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())){ | ||
955 | - return "N'%"+str+"%'"; | ||
956 | - }else{ | ||
957 | - return "'%"+str+"%'"; | 992 | + |
993 | + //update-begin-author:taoyan date:2022-6-30 for: issues/3810 数据权限规则问题 | ||
994 | + // 走到这里说明 value不带有任何模糊查询的标识(*或者%) | ||
995 | + if (ruleEnum == QueryRuleEnum.LEFT_LIKE) { | ||
996 | + if (DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())) { | ||
997 | + return "N'%" + str + "'"; | ||
998 | + } else { | ||
999 | + return "'%" + str + "'"; | ||
1000 | + } | ||
1001 | + } else if (ruleEnum == QueryRuleEnum.RIGHT_LIKE) { | ||
1002 | + if (DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())) { | ||
1003 | + return "N'" + str + "%'"; | ||
1004 | + } else { | ||
1005 | + return "'" + str + "%'"; | ||
1006 | + } | ||
1007 | + } else { | ||
1008 | + if (DataBaseConstant.DB_TYPE_SQLSERVER.equals(getDbType())) { | ||
1009 | + return "N'%" + str + "%'"; | ||
1010 | + } else { | ||
1011 | + return "'%" + str + "%'"; | ||
1012 | + } | ||
958 | } | 1013 | } |
1014 | + //update-end-author:taoyan date:2022-6-30 for: issues/3810 数据权限规则问题 | ||
1015 | + | ||
959 | } | 1016 | } |
960 | } | 1017 | } |
961 | } | 1018 | } |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/util/JwtUtil.java
@@ -54,7 +54,7 @@ public class JwtUtil { | @@ -54,7 +54,7 @@ public class JwtUtil { | ||
54 | try { | 54 | try { |
55 | os = httpServletResponse.getOutputStream(); | 55 | os = httpServletResponse.getOutputStream(); |
56 | httpServletResponse.setCharacterEncoding("UTF-8"); | 56 | httpServletResponse.setCharacterEncoding("UTF-8"); |
57 | - httpServletResponse.setStatus(401); | 57 | + httpServletResponse.setStatus(code); |
58 | os.write(new ObjectMapper().writeValueAsString(jsonResult).getBytes("UTF-8")); | 58 | os.write(new ObjectMapper().writeValueAsString(jsonResult).getBytes("UTF-8")); |
59 | os.flush(); | 59 | os.flush(); |
60 | os.close(); | 60 | os.close(); |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/util/ResourceUtil.java
0 → 100644
1 | +package org.jeecg.common.system.util; | ||
2 | + | ||
3 | +import lombok.extern.slf4j.Slf4j; | ||
4 | +import org.jeecg.common.system.annotation.EnumDict; | ||
5 | +import org.jeecg.common.system.vo.DictModel; | ||
6 | +import org.jeecg.common.util.oConvertUtils; | ||
7 | +import org.springframework.core.io.Resource; | ||
8 | +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; | ||
9 | +import org.springframework.core.io.support.ResourcePatternResolver; | ||
10 | +import org.springframework.core.type.classreading.CachingMetadataReaderFactory; | ||
11 | +import org.springframework.core.type.classreading.MetadataReader; | ||
12 | +import org.springframework.core.type.classreading.MetadataReaderFactory; | ||
13 | +import org.springframework.util.ClassUtils; | ||
14 | + | ||
15 | +import java.util.ArrayList; | ||
16 | +import java.util.HashMap; | ||
17 | +import java.util.List; | ||
18 | +import java.util.Map; | ||
19 | + | ||
20 | +/** | ||
21 | + * 资源加载工具类 | ||
22 | + * @Author taoYan | ||
23 | + * @Date 2022/7/8 10:40 | ||
24 | + **/ | ||
25 | +@Slf4j | ||
26 | +public class ResourceUtil { | ||
27 | + | ||
28 | + | ||
29 | + /** | ||
30 | + * 枚举字典数据 | ||
31 | + */ | ||
32 | + private final static Map<String, List<DictModel>> enumDictData = new HashMap<>(5); | ||
33 | + | ||
34 | + /** | ||
35 | + * 所有java类 | ||
36 | + */ | ||
37 | + private final static String CLASS_PATTERN="/**/*.class"; | ||
38 | + | ||
39 | + /** | ||
40 | + * 包路径 org.jeecg | ||
41 | + */ | ||
42 | + private final static String BASE_PACKAGE = "org.jeecg"; | ||
43 | + | ||
44 | + /** | ||
45 | + * 枚举类中获取字典数据的方法名 | ||
46 | + */ | ||
47 | + private final static String METHOD_NAME = "getDictList"; | ||
48 | + | ||
49 | + /** | ||
50 | + * 获取枚举类对应的字典数据 SysDictServiceImpl#queryAllDictItems() | ||
51 | + * @return | ||
52 | + */ | ||
53 | + public static Map<String, List<DictModel>> getEnumDictData(){ | ||
54 | + if(enumDictData.keySet().size()>0){ | ||
55 | + return enumDictData; | ||
56 | + } | ||
57 | + ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); | ||
58 | + String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + ClassUtils.convertClassNameToResourcePath(BASE_PACKAGE) + CLASS_PATTERN; | ||
59 | + try { | ||
60 | + Resource[] resources = resourcePatternResolver.getResources(pattern); | ||
61 | + MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(resourcePatternResolver); | ||
62 | + for (Resource resource : resources) { | ||
63 | + MetadataReader reader = readerFactory.getMetadataReader(resource); | ||
64 | + String classname = reader.getClassMetadata().getClassName(); | ||
65 | + Class<?> clazz = Class.forName(classname); | ||
66 | + EnumDict enumDict = clazz.getAnnotation(EnumDict.class); | ||
67 | + if (enumDict != null) { | ||
68 | + EnumDict annotation = clazz.getAnnotation(EnumDict.class); | ||
69 | + String key = annotation.value(); | ||
70 | + if(oConvertUtils.isNotEmpty(key)){ | ||
71 | + List<DictModel> list = (List<DictModel>) clazz.getDeclaredMethod(METHOD_NAME).invoke(null); | ||
72 | + enumDictData.put(key, list); | ||
73 | + } | ||
74 | + } | ||
75 | + } | ||
76 | + }catch (Exception e){ | ||
77 | + log.error("获取枚举类字典数据异常", e.getMessage()); | ||
78 | + // e.printStackTrace(); | ||
79 | + } | ||
80 | + return enumDictData; | ||
81 | + } | ||
82 | + | ||
83 | + /** | ||
84 | + * 用于后端字典翻译 SysDictServiceImpl#queryManyDictByKeys(java.util.List, java.util.List) | ||
85 | + * @param dictCodeList | ||
86 | + * @param keys | ||
87 | + * @return | ||
88 | + */ | ||
89 | + public static Map<String, List<DictModel>> queryManyDictByKeys(List<String> dictCodeList, List<String> keys){ | ||
90 | + if(enumDictData.keySet().size()==0){ | ||
91 | + getEnumDictData(); | ||
92 | + } | ||
93 | + Map<String, List<DictModel>> map = new HashMap<>(); | ||
94 | + for (String code : enumDictData.keySet()) { | ||
95 | + if(dictCodeList.indexOf(code)>=0){ | ||
96 | + List<DictModel> dictItemList = enumDictData.get(code); | ||
97 | + for(DictModel dm: dictItemList){ | ||
98 | + String value = dm.getValue(); | ||
99 | + if(keys.indexOf(value)>=0){ | ||
100 | + List<DictModel> list = new ArrayList<>(); | ||
101 | + list.add(new DictModel(value, dm.getText())); | ||
102 | + map.put(code,list); | ||
103 | + break; | ||
104 | + } | ||
105 | + } | ||
106 | + } | ||
107 | + } | ||
108 | + return map; | ||
109 | + } | ||
110 | + | ||
111 | +} |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/system/vo/LoginUser.java
@@ -2,6 +2,7 @@ package org.jeecg.common.system.vo; | @@ -2,6 +2,7 @@ package org.jeecg.common.system.vo; | ||
2 | 2 | ||
3 | import java.util.Date; | 3 | import java.util.Date; |
4 | 4 | ||
5 | +import org.jeecg.common.desensitization.annotation.SensitiveField; | ||
5 | import org.springframework.format.annotation.DateTimeFormat; | 6 | import org.springframework.format.annotation.DateTimeFormat; |
6 | 7 | ||
7 | import com.fasterxml.jackson.annotation.JsonFormat; | 8 | import com.fasterxml.jackson.annotation.JsonFormat; |
@@ -26,21 +27,25 @@ public class LoginUser { | @@ -26,21 +27,25 @@ public class LoginUser { | ||
26 | /** | 27 | /** |
27 | * 登录人id | 28 | * 登录人id |
28 | */ | 29 | */ |
30 | + @SensitiveField | ||
29 | private String id; | 31 | private String id; |
30 | 32 | ||
31 | /** | 33 | /** |
32 | * 登录人账号 | 34 | * 登录人账号 |
33 | */ | 35 | */ |
36 | + @SensitiveField | ||
34 | private String username; | 37 | private String username; |
35 | 38 | ||
36 | /** | 39 | /** |
37 | * 登录人名字 | 40 | * 登录人名字 |
38 | */ | 41 | */ |
42 | + @SensitiveField | ||
39 | private String realname; | 43 | private String realname; |
40 | 44 | ||
41 | /** | 45 | /** |
42 | * 登录人密码 | 46 | * 登录人密码 |
43 | */ | 47 | */ |
48 | + @SensitiveField | ||
44 | private String password; | 49 | private String password; |
45 | 50 | ||
46 | /** | 51 | /** |
@@ -50,11 +55,13 @@ public class LoginUser { | @@ -50,11 +55,13 @@ public class LoginUser { | ||
50 | /** | 55 | /** |
51 | * 头像 | 56 | * 头像 |
52 | */ | 57 | */ |
58 | + @SensitiveField | ||
53 | private String avatar; | 59 | private String avatar; |
54 | 60 | ||
55 | /** | 61 | /** |
56 | * 生日 | 62 | * 生日 |
57 | */ | 63 | */ |
64 | + @SensitiveField | ||
58 | @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") | 65 | @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd") |
59 | @DateTimeFormat(pattern = "yyyy-MM-dd") | 66 | @DateTimeFormat(pattern = "yyyy-MM-dd") |
60 | private Date birthday; | 67 | private Date birthday; |
@@ -67,11 +74,13 @@ public class LoginUser { | @@ -67,11 +74,13 @@ public class LoginUser { | ||
67 | /** | 74 | /** |
68 | * 电子邮件 | 75 | * 电子邮件 |
69 | */ | 76 | */ |
77 | + @SensitiveField | ||
70 | private String email; | 78 | private String email; |
71 | 79 | ||
72 | /** | 80 | /** |
73 | * 电话 | 81 | * 电话 |
74 | */ | 82 | */ |
83 | + @SensitiveField | ||
75 | private String phone; | 84 | private String phone; |
76 | 85 | ||
77 | /** | 86 | /** |
@@ -103,11 +112,13 @@ public class LoginUser { | @@ -103,11 +112,13 @@ public class LoginUser { | ||
103 | /** | 112 | /** |
104 | * 职务,关联职务表 | 113 | * 职务,关联职务表 |
105 | */ | 114 | */ |
115 | + @SensitiveField | ||
106 | private String post; | 116 | private String post; |
107 | 117 | ||
108 | /** | 118 | /** |
109 | * 座机号 | 119 | * 座机号 |
110 | */ | 120 | */ |
121 | + @SensitiveField | ||
111 | private String telephone; | 122 | private String telephone; |
112 | 123 | ||
113 | /**多租户id配置,编辑用户的时候设置*/ | 124 | /**多租户id配置,编辑用户的时候设置*/ |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/CommonUtils.java
@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils; | @@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.extension.toolkit.JdbcUtils; | ||
7 | import lombok.extern.slf4j.Slf4j; | 7 | import lombok.extern.slf4j.Slf4j; |
8 | import org.jeecg.common.constant.CommonConstant; | 8 | import org.jeecg.common.constant.CommonConstant; |
9 | import org.jeecg.common.constant.DataBaseConstant; | 9 | import org.jeecg.common.constant.DataBaseConstant; |
10 | +import org.jeecg.common.constant.ServiceNameConstants; | ||
10 | import org.jeecg.common.constant.SymbolConstant; | 11 | import org.jeecg.common.constant.SymbolConstant; |
11 | import org.jeecg.common.util.filter.FileTypeFilter; | 12 | import org.jeecg.common.util.filter.FileTypeFilter; |
12 | import org.jeecg.common.util.oss.OssBootUtil; | 13 | import org.jeecg.common.util.oss.OssBootUtil; |
@@ -314,14 +315,14 @@ public class CommonUtils { | @@ -314,14 +315,14 @@ public class CommonUtils { | ||
314 | */ | 315 | */ |
315 | public static String getBaseUrl(HttpServletRequest request) { | 316 | public static String getBaseUrl(HttpServletRequest request) { |
316 | //1.【兼容】兼容微服务下的 base path------- | 317 | //1.【兼容】兼容微服务下的 base path------- |
317 | - String xGatewayBasePath = request.getHeader("X_GATEWAY_BASE_PATH"); | 318 | + String xGatewayBasePath = request.getHeader(ServiceNameConstants.X_GATEWAY_BASE_PATH); |
318 | if(oConvertUtils.isNotEmpty(xGatewayBasePath)){ | 319 | if(oConvertUtils.isNotEmpty(xGatewayBasePath)){ |
319 | log.info("x_gateway_base_path = "+ xGatewayBasePath); | 320 | log.info("x_gateway_base_path = "+ xGatewayBasePath); |
320 | return xGatewayBasePath; | 321 | return xGatewayBasePath; |
321 | } | 322 | } |
322 | //2.【兼容】SSL认证之后,request.getScheme()获取不到https的问题 | 323 | //2.【兼容】SSL认证之后,request.getScheme()获取不到https的问题 |
323 | // https://blog.csdn.net/weixin_34376986/article/details/89767950 | 324 | // https://blog.csdn.net/weixin_34376986/article/details/89767950 |
324 | - String scheme = request.getHeader("X-Forwarded-Scheme"); | 325 | + String scheme = request.getHeader(CommonConstant.X_FORWARDED_SCHEME); |
325 | if(oConvertUtils.isEmpty(scheme)){ | 326 | if(oConvertUtils.isEmpty(scheme)){ |
326 | scheme = request.getScheme(); | 327 | scheme = request.getScheme(); |
327 | } | 328 | } |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/RestUtil.java
@@ -214,7 +214,7 @@ public class RestUtil { | @@ -214,7 +214,7 @@ public class RestUtil { | ||
214 | } | 214 | } |
215 | } | 215 | } |
216 | // 拼接 url 参数 | 216 | // 拼接 url 参数 |
217 | - if (variables != null) { | 217 | + if (variables != null && !variables.isEmpty()) { |
218 | url += ("?" + asUrlVariables(variables)); | 218 | url += ("?" + asUrlVariables(variables)); |
219 | } | 219 | } |
220 | // 发送请求 | 220 | // 发送请求 |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/SqlInjectionUtil.java
@@ -4,6 +4,8 @@ import cn.hutool.crypto.SecureUtil; | @@ -4,6 +4,8 @@ import cn.hutool.crypto.SecureUtil; | ||
4 | import lombok.extern.slf4j.Slf4j; | 4 | import lombok.extern.slf4j.Slf4j; |
5 | import org.jeecg.common.exception.JeecgBootException; | 5 | import org.jeecg.common.exception.JeecgBootException; |
6 | import javax.servlet.http.HttpServletRequest; | 6 | import javax.servlet.http.HttpServletRequest; |
7 | +import java.lang.reflect.Field; | ||
8 | +import java.util.Set; | ||
7 | import java.util.regex.Pattern; | 9 | import java.util.regex.Pattern; |
8 | 10 | ||
9 | /** | 11 | /** |
@@ -20,7 +22,11 @@ public class SqlInjectionUtil { | @@ -20,7 +22,11 @@ public class SqlInjectionUtil { | ||
20 | private final static String TABLE_DICT_SIGN_SALT = "20200501"; | 22 | private final static String TABLE_DICT_SIGN_SALT = "20200501"; |
21 | private final static String XSS_STR = "and |exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |;|or |+|user()"; | 23 | private final static String XSS_STR = "and |exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |;|or |+|user()"; |
22 | 24 | ||
23 | - /**show tables*/ | 25 | + /** |
26 | + * 正则 user() 匹配更严谨 | ||
27 | + */ | ||
28 | + private final static String REGULAR_EXPRE_USER = "user[\\s]*\\([\\s]*\\)"; | ||
29 | + /**正则 show tables*/ | ||
24 | private final static String SHOW_TABLES = "show\\s+tables"; | 30 | private final static String SHOW_TABLES = "show\\s+tables"; |
25 | 31 | ||
26 | /** | 32 | /** |
@@ -42,6 +48,13 @@ public class SqlInjectionUtil { | @@ -42,6 +48,13 @@ public class SqlInjectionUtil { | ||
42 | log.info(" 表字典,SQL注入漏洞签名校验成功!sign=" + sign + ",dictCode=" + dictCode); | 48 | log.info(" 表字典,SQL注入漏洞签名校验成功!sign=" + sign + ",dictCode=" + dictCode); |
43 | } | 49 | } |
44 | 50 | ||
51 | + /** | ||
52 | + * sql注入过滤处理,遇到注入关键字抛异常 | ||
53 | + * @param value | ||
54 | + */ | ||
55 | + public static void filterContent(String value) { | ||
56 | + filterContent(value, null); | ||
57 | + } | ||
45 | 58 | ||
46 | /** | 59 | /** |
47 | * sql注入过滤处理,遇到注入关键字抛异常 | 60 | * sql注入过滤处理,遇到注入关键字抛异常 |
@@ -49,7 +62,7 @@ public class SqlInjectionUtil { | @@ -49,7 +62,7 @@ public class SqlInjectionUtil { | ||
49 | * @param value | 62 | * @param value |
50 | * @return | 63 | * @return |
51 | */ | 64 | */ |
52 | - public static void filterContent(String value) { | 65 | + public static void filterContent(String value, String customXssString) { |
53 | if (value == null || "".equals(value)) { | 66 | if (value == null || "".equals(value)) { |
54 | return; | 67 | return; |
55 | } | 68 | } |
@@ -66,7 +79,19 @@ public class SqlInjectionUtil { | @@ -66,7 +79,19 @@ public class SqlInjectionUtil { | ||
66 | throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value); | 79 | throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value); |
67 | } | 80 | } |
68 | } | 81 | } |
69 | - if(Pattern.matches(SHOW_TABLES, value)){ | 82 | + //update-begin-author:taoyan date:2022-7-13 for: 除了XSS_STR这些提前设置好的,还需要额外的校验比如 单引号 |
83 | + if (customXssString != null) { | ||
84 | + String[] xssArr2 = customXssString.split("\\|"); | ||
85 | + for (int i = 0; i < xssArr2.length; i++) { | ||
86 | + if (value.indexOf(xssArr2[i]) > -1) { | ||
87 | + log.error("请注意,存在SQL注入关键词---> {}", xssArr2[i]); | ||
88 | + log.error("请注意,值可能存在SQL注入风险!---> {}", value); | ||
89 | + throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value); | ||
90 | + } | ||
91 | + } | ||
92 | + } | ||
93 | + //update-end-author:taoyan date:2022-7-13 for: 除了XSS_STR这些提前设置好的,还需要额外的校验比如 单引号 | ||
94 | + if(Pattern.matches(SHOW_TABLES, value) || Pattern.matches(REGULAR_EXPRE_USER, value)){ | ||
70 | throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value); | 95 | throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value); |
71 | } | 96 | } |
72 | return; | 97 | return; |
@@ -74,11 +99,19 @@ public class SqlInjectionUtil { | @@ -74,11 +99,19 @@ public class SqlInjectionUtil { | ||
74 | 99 | ||
75 | /** | 100 | /** |
76 | * sql注入过滤处理,遇到注入关键字抛异常 | 101 | * sql注入过滤处理,遇到注入关键字抛异常 |
102 | + * @param values | ||
103 | + */ | ||
104 | + public static void filterContent(String[] values) { | ||
105 | + filterContent(values, null); | ||
106 | + } | ||
107 | + | ||
108 | + /** | ||
109 | + * sql注入过滤处理,遇到注入关键字抛异常 | ||
77 | * | 110 | * |
78 | * @param values | 111 | * @param values |
79 | * @return | 112 | * @return |
80 | */ | 113 | */ |
81 | - public static void filterContent(String[] values) { | 114 | + public static void filterContent(String[] values, String customXssString) { |
82 | String[] xssArr = XSS_STR.split("\\|"); | 115 | String[] xssArr = XSS_STR.split("\\|"); |
83 | for (String value : values) { | 116 | for (String value : values) { |
84 | if (value == null || "".equals(value)) { | 117 | if (value == null || "".equals(value)) { |
@@ -96,7 +129,19 @@ public class SqlInjectionUtil { | @@ -96,7 +129,19 @@ public class SqlInjectionUtil { | ||
96 | throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value); | 129 | throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value); |
97 | } | 130 | } |
98 | } | 131 | } |
99 | - if(Pattern.matches(SHOW_TABLES, value)){ | 132 | + //update-begin-author:taoyan date:2022-7-13 for: 除了XSS_STR这些提前设置好的,还需要额外的校验比如 单引号 |
133 | + if (customXssString != null) { | ||
134 | + String[] xssArr2 = customXssString.split("\\|"); | ||
135 | + for (int i = 0; i < xssArr2.length; i++) { | ||
136 | + if (value.indexOf(xssArr2[i]) > -1) { | ||
137 | + log.error("请注意,存在SQL注入关键词---> {}", xssArr2[i]); | ||
138 | + log.error("请注意,值可能存在SQL注入风险!---> {}", value); | ||
139 | + throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value); | ||
140 | + } | ||
141 | + } | ||
142 | + } | ||
143 | + //update-end-author:taoyan date:2022-7-13 for: 除了XSS_STR这些提前设置好的,还需要额外的校验比如 单引号 | ||
144 | + if(Pattern.matches(SHOW_TABLES, value) || Pattern.matches(REGULAR_EXPRE_USER, value)){ | ||
100 | throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value); | 145 | throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value); |
101 | } | 146 | } |
102 | } | 147 | } |
@@ -111,8 +156,8 @@ public class SqlInjectionUtil { | @@ -111,8 +156,8 @@ public class SqlInjectionUtil { | ||
111 | * @return | 156 | * @return |
112 | */ | 157 | */ |
113 | //@Deprecated | 158 | //@Deprecated |
114 | - public static void specialFilterContent(String value) { | ||
115 | - String specialXssStr = " exec | insert | select | delete | update | drop | count | chr | mid | master | truncate | char | declare |;|+|"; | 159 | + public static void specialFilterContentForDictSql(String value) { |
160 | + String specialXssStr = " exec | insert | select | delete | update | drop | count | chr | mid | master | truncate | char | declare |;|+|user()"; | ||
116 | String[] xssArr = specialXssStr.split("\\|"); | 161 | String[] xssArr = specialXssStr.split("\\|"); |
117 | if (value == null || "".equals(value)) { | 162 | if (value == null || "".equals(value)) { |
118 | return; | 163 | return; |
@@ -129,7 +174,7 @@ public class SqlInjectionUtil { | @@ -129,7 +174,7 @@ public class SqlInjectionUtil { | ||
129 | throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value); | 174 | throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value); |
130 | } | 175 | } |
131 | } | 176 | } |
132 | - if(Pattern.matches(SHOW_TABLES, value)){ | 177 | + if(Pattern.matches(SHOW_TABLES, value) || Pattern.matches(REGULAR_EXPRE_USER, value)){ |
133 | throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value); | 178 | throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value); |
134 | } | 179 | } |
135 | return; | 180 | return; |
@@ -144,7 +189,7 @@ public class SqlInjectionUtil { | @@ -144,7 +189,7 @@ public class SqlInjectionUtil { | ||
144 | */ | 189 | */ |
145 | //@Deprecated | 190 | //@Deprecated |
146 | public static void specialFilterContentForOnlineReport(String value) { | 191 | public static void specialFilterContentForOnlineReport(String value) { |
147 | - String specialXssStr = " exec | insert | delete | update | drop | chr | mid | master | truncate | char | declare |"; | 192 | + String specialXssStr = " exec | insert | delete | update | drop | chr | mid | master | truncate | char | declare |user()"; |
148 | String[] xssArr = specialXssStr.split("\\|"); | 193 | String[] xssArr = specialXssStr.split("\\|"); |
149 | if (value == null || "".equals(value)) { | 194 | if (value == null || "".equals(value)) { |
150 | return; | 195 | return; |
@@ -162,10 +207,53 @@ public class SqlInjectionUtil { | @@ -162,10 +207,53 @@ public class SqlInjectionUtil { | ||
162 | } | 207 | } |
163 | } | 208 | } |
164 | 209 | ||
165 | - if(Pattern.matches(SHOW_TABLES, value)){ | 210 | + if(Pattern.matches(SHOW_TABLES, value) || Pattern.matches(REGULAR_EXPRE_USER, value)){ |
166 | throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value); | 211 | throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value); |
167 | } | 212 | } |
168 | return; | 213 | return; |
169 | } | 214 | } |
170 | 215 | ||
216 | + | ||
217 | + /** | ||
218 | + * 判断给定的字段是不是类中的属性 | ||
219 | + * @param field 字段名 | ||
220 | + * @param clazz 类对象 | ||
221 | + * @return | ||
222 | + */ | ||
223 | + public static boolean isClassField(String field, Class clazz){ | ||
224 | + Field[] fields = clazz.getDeclaredFields(); | ||
225 | + for(int i=0;i<fields.length;i++){ | ||
226 | + String fieldName = fields[i].getName(); | ||
227 | + String tableColumnName = oConvertUtils.camelToUnderline(fieldName); | ||
228 | + if(fieldName.equalsIgnoreCase(field) || tableColumnName.equalsIgnoreCase(field)){ | ||
229 | + return true; | ||
230 | + } | ||
231 | + } | ||
232 | + return false; | ||
233 | + } | ||
234 | + | ||
235 | + /** | ||
236 | + * 判断给定的多个字段是不是类中的属性 | ||
237 | + * @param fieldSet 字段名set | ||
238 | + * @param clazz 类对象 | ||
239 | + * @return | ||
240 | + */ | ||
241 | + public static boolean isClassField(Set<String> fieldSet, Class clazz){ | ||
242 | + Field[] fields = clazz.getDeclaredFields(); | ||
243 | + for(String field: fieldSet){ | ||
244 | + boolean exist = false; | ||
245 | + for(int i=0;i<fields.length;i++){ | ||
246 | + String fieldName = fields[i].getName(); | ||
247 | + String tableColumnName = oConvertUtils.camelToUnderline(fieldName); | ||
248 | + if(fieldName.equalsIgnoreCase(field) || tableColumnName.equalsIgnoreCase(field)){ | ||
249 | + exist = true; | ||
250 | + break; | ||
251 | + } | ||
252 | + } | ||
253 | + if(!exist){ | ||
254 | + return false; | ||
255 | + } | ||
256 | + } | ||
257 | + return true; | ||
258 | + } | ||
171 | } | 259 | } |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/TokenUtils.java
@@ -5,6 +5,7 @@ import org.apache.commons.lang3.StringUtils; | @@ -5,6 +5,7 @@ import org.apache.commons.lang3.StringUtils; | ||
5 | import org.jeecg.common.api.CommonAPI; | 5 | import org.jeecg.common.api.CommonAPI; |
6 | import org.jeecg.common.constant.CacheConstant; | 6 | import org.jeecg.common.constant.CacheConstant; |
7 | import org.jeecg.common.constant.CommonConstant; | 7 | import org.jeecg.common.constant.CommonConstant; |
8 | +import org.jeecg.common.desensitization.util.SensitiveInfoUtil; | ||
8 | import org.jeecg.common.exception.JeecgBoot401Exception; | 9 | import org.jeecg.common.exception.JeecgBoot401Exception; |
9 | import org.jeecg.common.system.util.JwtUtil; | 10 | import org.jeecg.common.system.util.JwtUtil; |
10 | import org.jeecg.common.system.vo.LoginUser; | 11 | import org.jeecg.common.system.vo.LoginUser; |
@@ -106,9 +107,16 @@ public class TokenUtils { | @@ -106,9 +107,16 @@ public class TokenUtils { | ||
106 | public static LoginUser getLoginUser(String username, CommonAPI commonApi, RedisUtil redisUtil) { | 107 | public static LoginUser getLoginUser(String username, CommonAPI commonApi, RedisUtil redisUtil) { |
107 | LoginUser loginUser = null; | 108 | LoginUser loginUser = null; |
108 | String loginUserKey = CacheConstant.SYS_USERS_CACHE + "::" + username; | 109 | String loginUserKey = CacheConstant.SYS_USERS_CACHE + "::" + username; |
109 | - if(redisUtil.hasKey(loginUserKey)){ | ||
110 | - loginUser = (LoginUser) redisUtil.get(loginUserKey); | ||
111 | - }else{ | 110 | + //【重要】此处通过redis原生获取缓存用户,是为了解决微服务下system服务挂了,其他服务互调不通问题--- |
111 | + if (redisUtil.hasKey(loginUserKey)) { | ||
112 | + try { | ||
113 | + loginUser = (LoginUser) redisUtil.get(loginUserKey); | ||
114 | + //解密用户 | ||
115 | + SensitiveInfoUtil.handlerObject(loginUser, false); | ||
116 | + } catch (IllegalAccessException e) { | ||
117 | + e.printStackTrace(); | ||
118 | + } | ||
119 | + } else { | ||
112 | // 查询用户信息 | 120 | // 查询用户信息 |
113 | loginUser = commonApi.getUserByName(username); | 121 | loginUser = commonApi.getUserByName(username); |
114 | } | 122 | } |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/encryption/AesEncryptUtil.java
@@ -66,22 +66,20 @@ public class AesEncryptUtil { | @@ -66,22 +66,20 @@ public class AesEncryptUtil { | ||
66 | * @throws Exception | 66 | * @throws Exception |
67 | */ | 67 | */ |
68 | public static String desEncrypt(String data, String key, String iv) throws Exception { | 68 | public static String desEncrypt(String data, String key, String iv) throws Exception { |
69 | - try { | ||
70 | - byte[] encrypted1 = Base64.decode(data); | 69 | + //update-begin-author:taoyan date:2022-5-23 for:VUEN-1084 【vue3】online表单测试发现的新问题 6、解密报错 ---解码失败应该把异常抛出去,在外面处理 |
70 | + byte[] encrypted1 = Base64.decode(data); | ||
71 | 71 | ||
72 | - Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); | ||
73 | - SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES"); | ||
74 | - IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes()); | 72 | + Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); |
73 | + SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES"); | ||
74 | + IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes()); | ||
75 | 75 | ||
76 | - cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec); | 76 | + cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec); |
77 | 77 | ||
78 | - byte[] original = cipher.doFinal(encrypted1); | ||
79 | - String originalString = new String(original); | ||
80 | - return originalString; | ||
81 | - } catch (Exception e) { | ||
82 | - e.printStackTrace(); | ||
83 | - return null; | ||
84 | - } | 78 | + byte[] original = cipher.doFinal(encrypted1); |
79 | + String originalString = new String(original); | ||
80 | + //加密解码后的字符串会出现\u0000 | ||
81 | + return originalString.replaceAll("\\u0000", ""); | ||
82 | + //update-end-author:taoyan date:2022-5-23 for:VUEN-1084 【vue3】online表单测试发现的新问题 6、解密报错 ---解码失败应该把异常抛出去,在外面处理 | ||
85 | } | 83 | } |
86 | 84 | ||
87 | /** | 85 | /** |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/common/util/security/AbstractQueryBlackListHandler.java
@@ -168,7 +168,7 @@ public abstract class AbstractQueryBlackListHandler { | @@ -168,7 +168,7 @@ public abstract class AbstractQueryBlackListHandler { | ||
168 | 168 | ||
169 | public String getError(){ | 169 | public String getError(){ |
170 | // TODO | 170 | // TODO |
171 | - return "sql黑名单校验不通过,请联系管理员!"; | 171 | + return "系统设置了安全规则,敏感表和敏感字段禁止查询,联系管理员授权!"; |
172 | } | 172 | } |
173 | 173 | ||
174 | } | 174 | } |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/JeeccgBaseConfig.java renamed to jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/JeecgBaseConfig.java
1 | package org.jeecg.config; | 1 | package org.jeecg.config; |
2 | 2 | ||
3 | +import org.jeecg.config.vo.DomainUrl; | ||
4 | +import org.jeecg.config.vo.Path; | ||
3 | import org.jeecg.config.vo.Shiro; | 5 | import org.jeecg.config.vo.Shiro; |
4 | import org.springframework.boot.context.properties.ConfigurationProperties; | 6 | import org.springframework.boot.context.properties.ConfigurationProperties; |
5 | import org.springframework.stereotype.Component; | 7 | import org.springframework.stereotype.Component; |
@@ -9,9 +11,15 @@ import org.springframework.stereotype.Component; | @@ -9,9 +11,15 @@ import org.springframework.stereotype.Component; | ||
9 | * 加载项目配置 | 11 | * 加载项目配置 |
10 | * @author: jeecg-boot | 12 | * @author: jeecg-boot |
11 | */ | 13 | */ |
12 | -@Component("jeeccgBaseConfig") | 14 | +@Component("jeecgBaseConfig") |
13 | @ConfigurationProperties(prefix = "jeecg") | 15 | @ConfigurationProperties(prefix = "jeecg") |
14 | -public class JeeccgBaseConfig { | 16 | +public class JeecgBaseConfig { |
17 | + /** | ||
18 | + * 签名密钥串(字典等敏感接口) | ||
19 | + * @TODO 降低使用成本加的默认值,实际以 yml配置 为准 | ||
20 | + */ | ||
21 | + private String signatureSecret = "dd05f1c54d63749eda95f9fa6d49v442a"; | ||
22 | + | ||
15 | /** | 23 | /** |
16 | * 是否启用安全模式 | 24 | * 是否启用安全模式 |
17 | */ | 25 | */ |
@@ -21,10 +29,16 @@ public class JeeccgBaseConfig { | @@ -21,10 +29,16 @@ public class JeeccgBaseConfig { | ||
21 | */ | 29 | */ |
22 | private Shiro shiro; | 30 | private Shiro shiro; |
23 | /** | 31 | /** |
24 | - * 签名密钥串(字典等敏感接口) | ||
25 | - * @TODO 降低使用成本加的默认值,实际以 yml配置 为准 | 32 | + * 上传文件配置 |
26 | */ | 33 | */ |
27 | - private String signatureSecret = "dd05f1c54d63749eda95f9fa6d49v442a"; | 34 | + private Path path; |
35 | + | ||
36 | + /** | ||
37 | + * 前端页面访问地址 | ||
38 | + * pc: http://localhost:3100 | ||
39 | + * app: http://localhost:8051 | ||
40 | + */ | ||
41 | + private DomainUrl domainUrl; | ||
28 | 42 | ||
29 | public Boolean getSafeMode() { | 43 | public Boolean getSafeMode() { |
30 | return safeMode; | 44 | return safeMode; |
@@ -49,4 +63,20 @@ public class JeeccgBaseConfig { | @@ -49,4 +63,20 @@ public class JeeccgBaseConfig { | ||
49 | public void setShiro(Shiro shiro) { | 63 | public void setShiro(Shiro shiro) { |
50 | this.shiro = shiro; | 64 | this.shiro = shiro; |
51 | } | 65 | } |
66 | + | ||
67 | + public Path getPath() { | ||
68 | + return path; | ||
69 | + } | ||
70 | + | ||
71 | + public void setPath(Path path) { | ||
72 | + this.path = path; | ||
73 | + } | ||
74 | + | ||
75 | + public DomainUrl getDomainUrl() { | ||
76 | + return domainUrl; | ||
77 | + } | ||
78 | + | ||
79 | + public void setDomainUrl(DomainUrl domainUrl) { | ||
80 | + this.domainUrl = domainUrl; | ||
81 | + } | ||
52 | } | 82 | } |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/WebMvcConfiguration.java
@@ -145,4 +145,13 @@ public class WebMvcConfiguration implements WebMvcConfigurer { | @@ -145,4 +145,13 @@ public class WebMvcConfiguration implements WebMvcConfigurer { | ||
145 | return () -> meterRegistryPostProcessor.postProcessAfterInitialization(prometheusMeterRegistry, ""); | 145 | return () -> meterRegistryPostProcessor.postProcessAfterInitialization(prometheusMeterRegistry, ""); |
146 | } | 146 | } |
147 | 147 | ||
148 | +// /** | ||
149 | +// * 注册拦截器【拦截器拦截参数,自动切换数据源——后期实现多租户切换数据源功能】 | ||
150 | +// * @param registry | ||
151 | +// */ | ||
152 | +// @Override | ||
153 | +// public void addInterceptors(InterceptorRegistry registry) { | ||
154 | +// registry.addInterceptor(new DynamicDatasourceInterceptor()).addPathPatterns("/test/dynamic/**"); | ||
155 | +// } | ||
156 | + | ||
148 | } | 157 | } |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/mybatis/MybatisPlusSaasConfig.java
@@ -3,6 +3,9 @@ package org.jeecg.config.mybatis; | @@ -3,6 +3,9 @@ package org.jeecg.config.mybatis; | ||
3 | import java.util.ArrayList; | 3 | import java.util.ArrayList; |
4 | import java.util.List; | 4 | import java.util.List; |
5 | 5 | ||
6 | +import cn.hutool.core.util.ObjectUtil; | ||
7 | +import com.baomidou.mybatisplus.extension.plugins.inner.DynamicTableNameInnerInterceptor; | ||
8 | +import org.jeecg.common.constant.CommonConstant; | ||
6 | import org.jeecg.common.util.oConvertUtils; | 9 | import org.jeecg.common.util.oConvertUtils; |
7 | import org.mybatis.spring.annotation.MapperScan; | 10 | import org.mybatis.spring.annotation.MapperScan; |
8 | import org.springframework.context.annotation.Bean; | 11 | import org.springframework.context.annotation.Bean; |
@@ -71,9 +74,35 @@ public class MybatisPlusSaasConfig { | @@ -71,9 +74,35 @@ public class MybatisPlusSaasConfig { | ||
71 | } | 74 | } |
72 | })); | 75 | })); |
73 | interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); | 76 | interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); |
77 | + //update-begin-author:zyf date:20220425 for:【VUEN-606】注入动态表名适配拦截器解决多表名问题 | ||
78 | + interceptor.addInnerInterceptor(dynamicTableNameInnerInterceptor()); | ||
79 | + //update-end-author:zyf date:20220425 for:【VUEN-606】注入动态表名适配拦截器解决多表名问题 | ||
74 | return interceptor; | 80 | return interceptor; |
75 | } | 81 | } |
76 | 82 | ||
83 | + /** | ||
84 | + * 动态表名切换拦截器,用于适配vue2和vue3同一个表有多个的情况,如sys_role_index在vue3情况下表名为sys_role_index_v3 | ||
85 | + * @return | ||
86 | + */ | ||
87 | + private DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor() { | ||
88 | + DynamicTableNameInnerInterceptor dynamicTableNameInnerInterceptor = new DynamicTableNameInnerInterceptor(); | ||
89 | + dynamicTableNameInnerInterceptor.setTableNameHandler((sql, tableName) -> { | ||
90 | + //获取需要动态解析的表名 | ||
91 | + String dynamicTableName = ThreadLocalDataHelper.get(CommonConstant.DYNAMIC_TABLE_NAME); | ||
92 | + //当dynamicTableName不为空时才走动态表名处理逻辑,否则返回原始表名 | ||
93 | + if (ObjectUtil.isNotEmpty(dynamicTableName) && dynamicTableName.equals(tableName)) { | ||
94 | + // 获取前端传递的版本号标识 | ||
95 | + Object version = ThreadLocalDataHelper.get(CommonConstant.VERSION); | ||
96 | + if (ObjectUtil.isNotEmpty(version)) { | ||
97 | + //拼接表名规则(原始表名+下划线+前端传递的版本号) | ||
98 | + return tableName + "_" + version; | ||
99 | + } | ||
100 | + } | ||
101 | + return tableName; | ||
102 | + }); | ||
103 | + return dynamicTableNameInnerInterceptor; | ||
104 | + } | ||
105 | + | ||
77 | // /** | 106 | // /** |
78 | // * 下个版本会删除,现在为了避免缓存出现问题不得不配置 | 107 | // * 下个版本会删除,现在为了避免缓存出现问题不得不配置 |
79 | // * @return | 108 | // * @return |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/mybatis/ThreadLocalDataHelper.java
0 → 100644
1 | +package org.jeecg.config.mybatis; | ||
2 | + | ||
3 | +import cn.hutool.core.util.ObjectUtil; | ||
4 | +import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; | ||
5 | +import java.util.concurrent.ConcurrentHashMap; | ||
6 | + | ||
7 | + | ||
8 | +/** | ||
9 | + * @Description: 本地线程变量存储工具类 | ||
10 | + * @author: lsq | ||
11 | + * @date: 2022年03月25日 11:42 | ||
12 | + */ | ||
13 | +public class ThreadLocalDataHelper { | ||
14 | + /** | ||
15 | + * 线程的本地变量 | ||
16 | + */ | ||
17 | + private static final ThreadLocal<ConcurrentHashMap> REQUEST_DATA = new ThreadLocal<>(); | ||
18 | + | ||
19 | + /** | ||
20 | + * 存储本地参数 | ||
21 | + */ | ||
22 | + private static final ConcurrentHashMap DATA_MAP = new ConcurrentHashMap<>(); | ||
23 | + | ||
24 | + /** | ||
25 | + * 设置请求参数 | ||
26 | + * | ||
27 | + * @param key 参数key | ||
28 | + * @param value 参数值 | ||
29 | + */ | ||
30 | + public static void put(String key, Object value) { | ||
31 | + if(ObjectUtil.isNotEmpty(value)) { | ||
32 | + DATA_MAP.put(key, value); | ||
33 | + REQUEST_DATA.set(DATA_MAP); | ||
34 | + } | ||
35 | + } | ||
36 | + | ||
37 | + /** | ||
38 | + * 获取请求参数值 | ||
39 | + * | ||
40 | + * @param key 请求参数 | ||
41 | + * @return | ||
42 | + */ | ||
43 | + public static <T> T get(String key) { | ||
44 | + ConcurrentHashMap dataMap = REQUEST_DATA.get(); | ||
45 | + if (CollectionUtils.isNotEmpty(dataMap)) { | ||
46 | + return (T) dataMap.get(key); | ||
47 | + } | ||
48 | + return null; | ||
49 | + } | ||
50 | + | ||
51 | + /** | ||
52 | + * 获取请求参数 | ||
53 | + * | ||
54 | + * @return 请求参数 MAP 对象 | ||
55 | + */ | ||
56 | + public static void clear() { | ||
57 | + DATA_MAP.clear(); | ||
58 | + REQUEST_DATA.remove(); | ||
59 | + } | ||
60 | + | ||
61 | +} | ||
62 | + |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/mybatis/aspect/DynamicTableAspect.java
0 → 100644
1 | +package org.jeecg.config.mybatis.aspect; | ||
2 | + | ||
3 | +import org.aspectj.lang.ProceedingJoinPoint; | ||
4 | +import org.aspectj.lang.annotation.Around; | ||
5 | +import org.aspectj.lang.annotation.Aspect; | ||
6 | +import org.aspectj.lang.annotation.Pointcut; | ||
7 | +import org.aspectj.lang.reflect.MethodSignature; | ||
8 | +import org.jeecg.common.aspect.annotation.DynamicTable; | ||
9 | +import org.jeecg.common.constant.CommonConstant; | ||
10 | +import org.jeecg.common.util.SpringContextUtils; | ||
11 | +import org.jeecg.config.mybatis.ThreadLocalDataHelper; | ||
12 | +import org.springframework.stereotype.Component; | ||
13 | + | ||
14 | +import javax.servlet.http.HttpServletRequest; | ||
15 | +import java.lang.reflect.Method; | ||
16 | + | ||
17 | +/** | ||
18 | + * 动态table切换 切面处理 | ||
19 | + * | ||
20 | + * @author :zyf | ||
21 | + * @date:2020-04-25 | ||
22 | + */ | ||
23 | +@Aspect | ||
24 | +@Component | ||
25 | +public class DynamicTableAspect { | ||
26 | + | ||
27 | + | ||
28 | + /** | ||
29 | + * 定义切面拦截切入点 | ||
30 | + */ | ||
31 | + @Pointcut("@annotation(org.jeecg.common.aspect.annotation.DynamicTable)") | ||
32 | + public void dynamicTable() { | ||
33 | + } | ||
34 | + | ||
35 | + | ||
36 | + @Around("dynamicTable()") | ||
37 | + public Object around(ProceedingJoinPoint point) throws Throwable { | ||
38 | + MethodSignature signature = (MethodSignature) point.getSignature(); | ||
39 | + Method method = signature.getMethod(); | ||
40 | + DynamicTable dynamicTable = method.getAnnotation(DynamicTable.class); | ||
41 | + HttpServletRequest request = SpringContextUtils.getHttpServletRequest(); | ||
42 | + //获取前端传递的版本标记 | ||
43 | + String version = request.getHeader(CommonConstant.VERSION); | ||
44 | + //存储版本号到本地线程变量 | ||
45 | + ThreadLocalDataHelper.put(CommonConstant.VERSION, version); | ||
46 | + //存储表名到本地线程变量 | ||
47 | + ThreadLocalDataHelper.put(CommonConstant.DYNAMIC_TABLE_NAME, dynamicTable.value()); | ||
48 | + //执行方法 | ||
49 | + Object result = point.proceed(); | ||
50 | + //清空本地变量 | ||
51 | + ThreadLocalDataHelper.clear(); | ||
52 | + return result; | ||
53 | + } | ||
54 | + | ||
55 | +} |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/mybatis/interceptor/DynamicDatasourceInterceptor.java
0 → 100644
1 | +package org.jeecg.config.mybatis.interceptor; | ||
2 | + | ||
3 | +import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder; | ||
4 | +import lombok.extern.slf4j.Slf4j; | ||
5 | +import org.apache.commons.lang3.StringUtils; | ||
6 | +import org.springframework.web.servlet.HandlerInterceptor; | ||
7 | +import org.springframework.web.servlet.ModelAndView; | ||
8 | + | ||
9 | +import javax.servlet.http.HttpServletRequest; | ||
10 | +import javax.servlet.http.HttpServletResponse; | ||
11 | + | ||
12 | +/** | ||
13 | + * 动态数据源切换拦截器 | ||
14 | + * | ||
15 | + * 测试:拦截参数,自动切换数据源 | ||
16 | + * 未来规划:后面通过此机制,实现多租户切换数据源功能 | ||
17 | + * @author zyf | ||
18 | + */ | ||
19 | +@Slf4j | ||
20 | +public class DynamicDatasourceInterceptor implements HandlerInterceptor { | ||
21 | + | ||
22 | + /** | ||
23 | + * 在请求处理之前进行调用(Controller方法调用之前) | ||
24 | + */ | ||
25 | + @Override | ||
26 | + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { | ||
27 | + String requestURI = request.getRequestURI(); | ||
28 | + log.info("经过多数据源Interceptor,当前路径是{}", requestURI); | ||
29 | + //获取动态数据源名称 | ||
30 | + String dsName = request.getParameter("dsName"); | ||
31 | + String dsKey = "master"; | ||
32 | + if (StringUtils.isNotEmpty(dsName)) { | ||
33 | + dsKey = dsName; | ||
34 | + } | ||
35 | + DynamicDataSourceContextHolder.push(dsKey); | ||
36 | + return true; | ||
37 | + } | ||
38 | + | ||
39 | + /** | ||
40 | + * 请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后) | ||
41 | + */ | ||
42 | + @Override | ||
43 | + public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { | ||
44 | + | ||
45 | + } | ||
46 | + | ||
47 | + /** | ||
48 | + * 在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作) | ||
49 | + */ | ||
50 | + @Override | ||
51 | + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { | ||
52 | + DynamicDataSourceContextHolder.clear(); | ||
53 | + } | ||
54 | + | ||
55 | +} | ||
0 | \ No newline at end of file | 56 | \ No newline at end of file |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroConfig.java
@@ -15,7 +15,7 @@ import org.crazycake.shiro.RedisClusterManager; | @@ -15,7 +15,7 @@ import org.crazycake.shiro.RedisClusterManager; | ||
15 | import org.crazycake.shiro.RedisManager; | 15 | import org.crazycake.shiro.RedisManager; |
16 | import org.jeecg.common.constant.CommonConstant; | 16 | import org.jeecg.common.constant.CommonConstant; |
17 | import org.jeecg.common.util.oConvertUtils; | 17 | import org.jeecg.common.util.oConvertUtils; |
18 | -import org.jeecg.config.JeeccgBaseConfig; | 18 | +import org.jeecg.config.JeecgBaseConfig; |
19 | import org.jeecg.config.shiro.filters.CustomShiroFilterFactoryBean; | 19 | import org.jeecg.config.shiro.filters.CustomShiroFilterFactoryBean; |
20 | import org.jeecg.config.shiro.filters.JwtFilter; | 20 | import org.jeecg.config.shiro.filters.JwtFilter; |
21 | import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; | 21 | import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; |
@@ -45,11 +45,11 @@ import java.util.*; | @@ -45,11 +45,11 @@ import java.util.*; | ||
45 | public class ShiroConfig { | 45 | public class ShiroConfig { |
46 | 46 | ||
47 | @Resource | 47 | @Resource |
48 | - LettuceConnectionFactory lettuceConnectionFactory; | 48 | + private LettuceConnectionFactory lettuceConnectionFactory; |
49 | @Autowired | 49 | @Autowired |
50 | private Environment env; | 50 | private Environment env; |
51 | - @Autowired | ||
52 | - JeeccgBaseConfig jeeccgBaseConfig; | 51 | + @Resource |
52 | + private JeecgBaseConfig jeecgBaseConfig; | ||
53 | 53 | ||
54 | /** | 54 | /** |
55 | * Filter Chain定义说明 | 55 | * Filter Chain定义说明 |
@@ -64,11 +64,15 @@ public class ShiroConfig { | @@ -64,11 +64,15 @@ public class ShiroConfig { | ||
64 | shiroFilterFactoryBean.setSecurityManager(securityManager); | 64 | shiroFilterFactoryBean.setSecurityManager(securityManager); |
65 | // 拦截器 | 65 | // 拦截器 |
66 | Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); | 66 | Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); |
67 | - String shiroExcludeUrls = jeeccgBaseConfig.getShiro().getExcludeUrls(); | ||
68 | - if(oConvertUtils.isNotEmpty(shiroExcludeUrls)){ | ||
69 | - String[] permissionUrl = shiroExcludeUrls.split(","); | ||
70 | - for(String url : permissionUrl){ | ||
71 | - filterChainDefinitionMap.put(url,"anon"); | 67 | + |
68 | + //支持yml方式,配置拦截排除 | ||
69 | + if(jeecgBaseConfig.getShiro()!=null){ | ||
70 | + String shiroExcludeUrls = jeecgBaseConfig.getShiro().getExcludeUrls(); | ||
71 | + if(oConvertUtils.isNotEmpty(shiroExcludeUrls)){ | ||
72 | + String[] permissionUrl = shiroExcludeUrls.split(","); | ||
73 | + for(String url : permissionUrl){ | ||
74 | + filterChainDefinitionMap.put(url,"anon"); | ||
75 | + } | ||
72 | } | 76 | } |
73 | } | 77 | } |
74 | // 配置不会被拦截的链接 顺序判断 | 78 | // 配置不会被拦截的链接 顺序判断 |
@@ -125,9 +129,11 @@ public class ShiroConfig { | @@ -125,9 +129,11 @@ public class ShiroConfig { | ||
125 | filterChainDefinitionMap.put("/jmreport/**", "anon"); | 129 | filterChainDefinitionMap.put("/jmreport/**", "anon"); |
126 | filterChainDefinitionMap.put("/**/*.js.map", "anon"); | 130 | filterChainDefinitionMap.put("/**/*.js.map", "anon"); |
127 | filterChainDefinitionMap.put("/**/*.css.map", "anon"); | 131 | filterChainDefinitionMap.put("/**/*.css.map", "anon"); |
128 | - | ||
129 | - //测试示例 | ||
130 | - filterChainDefinitionMap.put("/test/bigScreen/**", "anon"); //大屏模板例子 | 132 | + |
133 | + //大屏模板例子 | ||
134 | + filterChainDefinitionMap.put("/test/bigScreen/**", "anon"); | ||
135 | + filterChainDefinitionMap.put("/bigscreen/template1/**", "anon"); | ||
136 | + filterChainDefinitionMap.put("/bigscreen/template1/**", "anon"); | ||
131 | //filterChainDefinitionMap.put("/test/jeecgDemo/rabbitMqClientTest/**", "anon"); //MQ测试 | 137 | //filterChainDefinitionMap.put("/test/jeecgDemo/rabbitMqClientTest/**", "anon"); //MQ测试 |
132 | //filterChainDefinitionMap.put("/test/jeecgDemo/html", "anon"); //模板页面 | 138 | //filterChainDefinitionMap.put("/test/jeecgDemo/html", "anon"); //模板页面 |
133 | //filterChainDefinitionMap.put("/test/jeecgDemo/redis/**", "anon"); //redis测试 | 139 | //filterChainDefinitionMap.put("/test/jeecgDemo/redis/**", "anon"); //redis测试 |
@@ -137,8 +143,6 @@ public class ShiroConfig { | @@ -137,8 +143,6 @@ public class ShiroConfig { | ||
137 | filterChainDefinitionMap.put("/newsWebsocket/**", "anon");//CMS模块 | 143 | filterChainDefinitionMap.put("/newsWebsocket/**", "anon");//CMS模块 |
138 | filterChainDefinitionMap.put("/vxeSocket/**", "anon");//JVxeTable无痕刷新示例 | 144 | filterChainDefinitionMap.put("/vxeSocket/**", "anon");//JVxeTable无痕刷新示例 |
139 | 145 | ||
140 | - //wps | ||
141 | - filterChainDefinitionMap.put("/v1/**","anon"); | ||
142 | 146 | ||
143 | //性能监控 TODO 存在安全漏洞泄露TOEKN(durid连接池也有) | 147 | //性能监控 TODO 存在安全漏洞泄露TOEKN(durid连接池也有) |
144 | filterChainDefinitionMap.put("/actuator/**", "anon"); | 148 | filterChainDefinitionMap.put("/actuator/**", "anon"); |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/ShiroRealm.java
@@ -69,13 +69,13 @@ public class ShiroRealm extends AuthorizingRealm { | @@ -69,13 +69,13 @@ public class ShiroRealm extends AuthorizingRealm { | ||
69 | 69 | ||
70 | // 设置用户拥有的角色集合,比如“admin,test” | 70 | // 设置用户拥有的角色集合,比如“admin,test” |
71 | Set<String> roleSet = commonApi.queryUserRoles(username); | 71 | Set<String> roleSet = commonApi.queryUserRoles(username); |
72 | - System.out.println(roleSet.toString()); | 72 | + //System.out.println(roleSet.toString()); |
73 | info.setRoles(roleSet); | 73 | info.setRoles(roleSet); |
74 | 74 | ||
75 | // 设置用户拥有的权限集合,比如“sys:role:add,sys:user:add” | 75 | // 设置用户拥有的权限集合,比如“sys:role:add,sys:user:add” |
76 | Set<String> permissionSet = commonApi.queryUserAuths(username); | 76 | Set<String> permissionSet = commonApi.queryUserAuths(username); |
77 | info.addStringPermissions(permissionSet); | 77 | info.addStringPermissions(permissionSet); |
78 | - System.out.println(permissionSet); | 78 | + //System.out.println(permissionSet); |
79 | log.info("===============Shiro权限认证成功=============="); | 79 | log.info("===============Shiro权限认证成功=============="); |
80 | return info; | 80 | return info; |
81 | } | 81 | } |
@@ -123,7 +123,7 @@ public class ShiroRealm extends AuthorizingRealm { | @@ -123,7 +123,7 @@ public class ShiroRealm extends AuthorizingRealm { | ||
123 | 123 | ||
124 | // 查询用户信息 | 124 | // 查询用户信息 |
125 | log.debug("———校验token是否有效————checkUserTokenIsEffect——————— "+ token); | 125 | log.debug("———校验token是否有效————checkUserTokenIsEffect——————— "+ token); |
126 | - LoginUser loginUser = TokenUtils.getLoginUser(username,commonApi,redisUtil); | 126 | + LoginUser loginUser = TokenUtils.getLoginUser(username, commonApi, redisUtil); |
127 | //LoginUser loginUser = commonApi.getUserByName(username); | 127 | //LoginUser loginUser = commonApi.getUserByName(username); |
128 | if (loginUser == null) { | 128 | if (loginUser == null) { |
129 | throw new AuthenticationException("用户不存在!"); | 129 | throw new AuthenticationException("用户不存在!"); |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/shiro/filters/JwtFilter.java
@@ -107,4 +107,18 @@ public class JwtFilter extends BasicHttpAuthenticationFilter { | @@ -107,4 +107,18 @@ public class JwtFilter extends BasicHttpAuthenticationFilter { | ||
107 | 107 | ||
108 | return super.preHandle(request, response); | 108 | return super.preHandle(request, response); |
109 | } | 109 | } |
110 | + | ||
111 | + /** | ||
112 | + * JwtFilter中ThreadLocal需要及时清除 #3634 | ||
113 | + * | ||
114 | + * @param request | ||
115 | + * @param response | ||
116 | + * @param exception | ||
117 | + * @throws Exception | ||
118 | + */ | ||
119 | + @Override | ||
120 | + public void afterCompletion(ServletRequest request, ServletResponse response, Exception exception) throws Exception { | ||
121 | + //log.info("------清空线程中多租户的ID={}------",TenantContext.getTenant()); | ||
122 | + TenantContext.clear(); | ||
123 | + } | ||
110 | } | 124 | } |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/sign/interceptor/SignAuthConfiguration.java
1 | package org.jeecg.config.sign.interceptor; | 1 | package org.jeecg.config.sign.interceptor; |
2 | 2 | ||
3 | +import org.jeecg.config.filter.RequestBodyReserveFilter; | ||
4 | +import org.springframework.boot.web.servlet.FilterRegistrationBean; | ||
3 | import org.springframework.context.annotation.Bean; | 5 | import org.springframework.context.annotation.Bean; |
4 | import org.springframework.context.annotation.Configuration; | 6 | import org.springframework.context.annotation.Configuration; |
5 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; | 7 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; |
@@ -24,4 +26,22 @@ public class SignAuthConfiguration implements WebMvcConfigurer { | @@ -24,4 +26,22 @@ public class SignAuthConfiguration implements WebMvcConfigurer { | ||
24 | public void addInterceptors(InterceptorRegistry registry) { | 26 | public void addInterceptors(InterceptorRegistry registry) { |
25 | registry.addInterceptor(signAuthInterceptor()).addPathPatterns(SIGN_URL_LIST); | 27 | registry.addInterceptor(signAuthInterceptor()).addPathPatterns(SIGN_URL_LIST); |
26 | } | 28 | } |
29 | + | ||
30 | + //update-begin-author:taoyan date:20220427 for: issues/I53J5E post请求X_SIGN签名拦截校验后报错, request body 为空 | ||
31 | + @Bean | ||
32 | + public RequestBodyReserveFilter requestBodyReserveFilter(){ | ||
33 | + return new RequestBodyReserveFilter(); | ||
34 | + } | ||
35 | + | ||
36 | + @Bean | ||
37 | + public FilterRegistrationBean reqBodyFilterRegistrationBean(){ | ||
38 | + FilterRegistrationBean registration = new FilterRegistrationBean(); | ||
39 | + registration.setFilter(requestBodyReserveFilter()); | ||
40 | + registration.setName("requestBodyReserveFilter"); | ||
41 | + // 建议此处只添加post请求地址而不是所有的都需要走过滤器 | ||
42 | + registration.addUrlPatterns(SIGN_URL_LIST); | ||
43 | + return registration; | ||
44 | + } | ||
45 | + //update-end-author:taoyan date:20220427 for: issues/I53J5E post请求X_SIGN签名拦截校验后报错, request body 为空 | ||
46 | + | ||
27 | } | 47 | } |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/sign/interceptor/SignAuthInterceptor.java
@@ -32,7 +32,7 @@ public class SignAuthInterceptor implements HandlerInterceptor { | @@ -32,7 +32,7 @@ public class SignAuthInterceptor implements HandlerInterceptor { | ||
32 | 32 | ||
33 | @Override | 33 | @Override |
34 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { | 34 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { |
35 | - log.info("request URI = " + request.getRequestURI()); | 35 | + log.info("Sign Interceptor request URI = " + request.getRequestURI()); |
36 | HttpServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(request); | 36 | HttpServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper(request); |
37 | //获取全部参数(包括URL和body上的) | 37 | //获取全部参数(包括URL和body上的) |
38 | SortedMap<String, String> allParams = HttpUtils.getAllParams(requestWrapper); | 38 | SortedMap<String, String> allParams = HttpUtils.getAllParams(requestWrapper); |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/sign/util/SignUtil.java
@@ -6,7 +6,7 @@ import org.jeecg.common.constant.SymbolConstant; | @@ -6,7 +6,7 @@ import org.jeecg.common.constant.SymbolConstant; | ||
6 | import org.jeecg.common.exception.JeecgBootException; | 6 | import org.jeecg.common.exception.JeecgBootException; |
7 | import org.jeecg.common.util.SpringContextUtils; | 7 | import org.jeecg.common.util.SpringContextUtils; |
8 | import org.jeecg.common.util.oConvertUtils; | 8 | import org.jeecg.common.util.oConvertUtils; |
9 | -import org.jeecg.config.JeeccgBaseConfig; | 9 | +import org.jeecg.config.JeecgBaseConfig; |
10 | import org.springframework.util.DigestUtils; | 10 | import org.springframework.util.DigestUtils; |
11 | import org.springframework.util.StringUtils; | 11 | import org.springframework.util.StringUtils; |
12 | 12 | ||
@@ -48,8 +48,8 @@ public class SignUtil { | @@ -48,8 +48,8 @@ public class SignUtil { | ||
48 | String paramsJsonStr = JSONObject.toJSONString(params); | 48 | String paramsJsonStr = JSONObject.toJSONString(params); |
49 | log.info("Param paramsJsonStr : {}", paramsJsonStr); | 49 | log.info("Param paramsJsonStr : {}", paramsJsonStr); |
50 | //设置签名秘钥 | 50 | //设置签名秘钥 |
51 | - JeeccgBaseConfig jeeccgBaseConfig = SpringContextUtils.getBean(JeeccgBaseConfig.class); | ||
52 | - String signatureSecret = jeeccgBaseConfig.getSignatureSecret(); | 51 | + JeecgBaseConfig jeecgBaseConfig = SpringContextUtils.getBean(JeecgBaseConfig.class); |
52 | + String signatureSecret = jeecgBaseConfig.getSignatureSecret(); | ||
53 | String curlyBracket = SymbolConstant.DOLLAR + SymbolConstant.LEFT_CURLY_BRACKET; | 53 | String curlyBracket = SymbolConstant.DOLLAR + SymbolConstant.LEFT_CURLY_BRACKET; |
54 | if(oConvertUtils.isEmpty(signatureSecret) || signatureSecret.contains(curlyBracket)){ | 54 | if(oConvertUtils.isEmpty(signatureSecret) || signatureSecret.contains(curlyBracket)){ |
55 | throw new JeecgBootException("签名密钥 ${jeecg.signatureSecret} 缺少配置 !!"); | 55 | throw new JeecgBootException("签名密钥 ${jeecg.signatureSecret} 缺少配置 !!"); |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/vo/DomainUrl.java
0 → 100644
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/config/vo/Path.java
0 → 100644
1 | +package org.jeecg.config.vo; | ||
2 | + | ||
3 | +import javax.print.DocFlavor; | ||
4 | + | ||
5 | +/** | ||
6 | + * | ||
7 | + * @author: scott | ||
8 | + * @date: 2022年04月18日 20:35 | ||
9 | + */ | ||
10 | +public class Path { | ||
11 | + private String upload; | ||
12 | + private String webapp; | ||
13 | + | ||
14 | + public String getUpload() { | ||
15 | + return upload; | ||
16 | + } | ||
17 | + | ||
18 | + public void setUpload(String upload) { | ||
19 | + this.upload = upload; | ||
20 | + } | ||
21 | + | ||
22 | + public String getWebapp() { | ||
23 | + return webapp; | ||
24 | + } | ||
25 | + | ||
26 | + public void setWebapp(String webapp) { | ||
27 | + this.webapp = webapp; | ||
28 | + } | ||
29 | +} |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/mapper/xml/BaseCommonMapper.xml
@@ -4,19 +4,22 @@ | @@ -4,19 +4,22 @@ | ||
4 | 4 | ||
5 | <!-- 保存日志11 --> | 5 | <!-- 保存日志11 --> |
6 | <insert id="saveLog" parameterType="Object"> | 6 | <insert id="saveLog" parameterType="Object"> |
7 | - insert into sys_log (id, log_type, log_content, method, operate_type, request_param, ip, userid, username, cost_time, create_time) | 7 | + insert into sys_log (id, log_type, log_content, method, operate_type, request_url, request_type, request_param, ip, userid, username, cost_time, create_time,create_by) |
8 | values( | 8 | values( |
9 | #{dto.id,jdbcType=VARCHAR}, | 9 | #{dto.id,jdbcType=VARCHAR}, |
10 | #{dto.logType,jdbcType=INTEGER}, | 10 | #{dto.logType,jdbcType=INTEGER}, |
11 | #{dto.logContent,jdbcType=VARCHAR}, | 11 | #{dto.logContent,jdbcType=VARCHAR}, |
12 | #{dto.method,jdbcType=VARCHAR}, | 12 | #{dto.method,jdbcType=VARCHAR}, |
13 | #{dto.operateType,jdbcType=INTEGER}, | 13 | #{dto.operateType,jdbcType=INTEGER}, |
14 | + #{dto.requestUrl,jdbcType=VARCHAR}, | ||
15 | + #{dto.requestType,jdbcType=VARCHAR}, | ||
14 | #{dto.requestParam,jdbcType=VARCHAR}, | 16 | #{dto.requestParam,jdbcType=VARCHAR}, |
15 | #{dto.ip,jdbcType=VARCHAR}, | 17 | #{dto.ip,jdbcType=VARCHAR}, |
16 | #{dto.userid,jdbcType=VARCHAR}, | 18 | #{dto.userid,jdbcType=VARCHAR}, |
17 | #{dto.username,jdbcType=VARCHAR}, | 19 | #{dto.username,jdbcType=VARCHAR}, |
18 | #{dto.costTime,jdbcType=BIGINT}, | 20 | #{dto.costTime,jdbcType=BIGINT}, |
19 | - #{dto.createTime,jdbcType=TIMESTAMP} | 21 | + #{dto.createTime,jdbcType=TIMESTAMP}, |
22 | + #{dto.createBy,jdbcType=VARCHAR} | ||
20 | ) | 23 | ) |
21 | </insert> | 24 | </insert> |
22 | 25 |
jeecg-boot/jeecg-boot-base/jeecg-boot-base-core/src/main/java/org/jeecg/modules/base/service/impl/BaseCommonServiceImpl.java
@@ -34,6 +34,7 @@ public class BaseCommonServiceImpl implements BaseCommonService { | @@ -34,6 +34,7 @@ public class BaseCommonServiceImpl implements BaseCommonService { | ||
34 | } | 34 | } |
35 | //保存日志(异常捕获处理,防止数据太大存储失败,导致业务失败)JT-238 | 35 | //保存日志(异常捕获处理,防止数据太大存储失败,导致业务失败)JT-238 |
36 | try { | 36 | try { |
37 | + logDTO.setCreateTime(new Date()); | ||
37 | baseCommonMapper.saveLog(logDTO); | 38 | baseCommonMapper.saveLog(logDTO); |
38 | } catch (Exception e) { | 39 | } catch (Exception e) { |
39 | log.warn(" LogContent length : "+logDTO.getLogContent().length()); | 40 | log.warn(" LogContent length : "+logDTO.getLogContent().length()); |