From b3b6446433972422cf62dfc47c031134b91cd7ec Mon Sep 17 00:00:00 2001 From: Charles7c Date: Sun, 10 Sep 2023 22:35:50 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20:boom:=20=E5=88=86=E7=A6=BB=20HTTP?= =?UTF-8?q?=20=E7=8A=B6=E6=80=81=E7=A0=81=E5=92=8C=E4=B8=9A=E5=8A=A1?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1.传输正常的情况下无论业务是否有异常,HTTP 状态码始终为 200 2.防止非 HTTPS 情况下出现运营商劫持(例如:404) --- .../common/handler/GlobalErrorHandler.java | 4 +- .../handler/GlobalExceptionHandler.java | 14 ----- .../charles7c/cnadmin/common/model/vo/R.java | 8 +-- .../monitor/interceptor/LogInterceptor.java | 58 +++++++++---------- continew-admin-ui/src/utils/request.ts | 21 +++---- .../src/views/monitor/log/system/index.vue | 2 +- 6 files changed, 44 insertions(+), 63 deletions(-) diff --git a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/handler/GlobalErrorHandler.java b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/handler/GlobalErrorHandler.java index a07b8b7c..1ee3ed11 100644 --- a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/handler/GlobalErrorHandler.java +++ b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/handler/GlobalErrorHandler.java @@ -70,7 +70,7 @@ public class GlobalErrorHandler extends BasicErrorController { R result = R.fail(status.value(), (String)errorAttributeMap.get("error")); result.setData(path); try { - response.setStatus(status.value()); + response.setStatus(HttpStatus.OK.value()); response.setContentType(MediaType.APPLICATION_JSON_VALUE); objectMapper.writeValue(response.getWriter(), result); } catch (IOException e) { @@ -89,6 +89,6 @@ public class GlobalErrorHandler extends BasicErrorController { R result = R.fail(status.value(), (String)errorAttributeMap.get("error")); result.setData(path); log.error("请求地址 [{}],发生错误,错误信息:{}。", path, JSONUtil.toJsonStr(errorAttributeMap)); - return new ResponseEntity<>(BeanUtil.beanToMap(result), status); + return new ResponseEntity<>(BeanUtil.beanToMap(result), HttpStatus.OK); } } diff --git a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/handler/GlobalExceptionHandler.java b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/handler/GlobalExceptionHandler.java index b5042b3a..ac7e95d6 100644 --- a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/handler/GlobalExceptionHandler.java +++ b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/handler/GlobalExceptionHandler.java @@ -30,7 +30,6 @@ import org.springframework.validation.BindException; import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException; import org.springframework.web.multipart.MaxUploadSizeExceededException; @@ -62,7 +61,6 @@ public class GlobalExceptionHandler { /** * 拦截自定义验证异常-错误请求 */ - @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(BadRequestException.class) public R handleBadRequestException(BadRequestException e, HttpServletRequest request) { log.warn("请求地址 [{}],自定义验证失败。", request.getRequestURI(), e); @@ -73,7 +71,6 @@ public class GlobalExceptionHandler { /** * 拦截校验异常-违反约束异常 */ - @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(ConstraintViolationException.class) public R constraintViolationException(ConstraintViolationException e, HttpServletRequest request) { log.warn("请求地址 [{}],参数验证失败。", request.getRequestURI(), e); @@ -85,7 +82,6 @@ public class GlobalExceptionHandler { /** * 拦截校验异常-绑定异常 */ - @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(BindException.class) public R handleBindException(BindException e, HttpServletRequest request) { log.warn("请求地址 [{}],参数验证失败。", request.getRequestURI(), e); @@ -97,7 +93,6 @@ public class GlobalExceptionHandler { /** * 拦截校验异常-方法参数无效异常 */ - @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(MethodArgumentNotValidException.class) public R handleMethodArgumentNotValidException(MethodArgumentNotValidException e, HttpServletRequest request) { log.warn("请求地址 [{}],参数验证失败。", request.getRequestURI(), e); @@ -110,7 +105,6 @@ public class GlobalExceptionHandler { /** * 拦截校验异常-方法参数类型不匹配异常 */ - @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(MethodArgumentTypeMismatchException.class) public R handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request) { @@ -123,7 +117,6 @@ public class GlobalExceptionHandler { /** * 拦截文件上传异常-超过上传大小限制 */ - @ResponseStatus(HttpStatus.BAD_REQUEST) @ExceptionHandler(MaxUploadSizeExceededException.class) public R handleMaxUploadSizeExceededException(MaxUploadSizeExceededException e, HttpServletRequest request) { log.warn("请求地址 [{}],上传文件失败,文件大小超过限制。", request.getRequestURI(), e); @@ -136,7 +129,6 @@ public class GlobalExceptionHandler { /** * 认证异常-登录认证 */ - @ResponseStatus(HttpStatus.UNAUTHORIZED) @ExceptionHandler(NotLoginException.class) public R handleNotLoginException(NotLoginException e, HttpServletRequest request) { log.error("请求地址 [{}],认证失败,无法访问系统资源。", request.getRequestURI(), e); @@ -159,7 +151,6 @@ public class GlobalExceptionHandler { /** * 认证异常-权限认证 */ - @ResponseStatus(HttpStatus.FORBIDDEN) @ExceptionHandler(NotPermissionException.class) public R handleNotPermissionException(NotPermissionException e, HttpServletRequest request) { log.error("请求地址 [{}],权限码校验失败。", request.getRequestURI(), e); @@ -169,7 +160,6 @@ public class GlobalExceptionHandler { /** * 认证异常-角色认证 */ - @ResponseStatus(HttpStatus.FORBIDDEN) @ExceptionHandler(NotRoleException.class) public R handleNotRoleException(NotRoleException e, HttpServletRequest request) { log.error("请求地址 [{}],角色权限校验失败。", request.getRequestURI(), e); @@ -179,7 +169,6 @@ public class GlobalExceptionHandler { /** * 拦截校验异常-请求方式不支持异常 */ - @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED) @ExceptionHandler(HttpRequestMethodNotSupportedException.class) public R handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e, HttpServletRequest request) { LogContextHolder.setErrorMsg(e.getMessage()); @@ -190,7 +179,6 @@ public class GlobalExceptionHandler { /** * 拦截业务异常 */ - @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ExceptionHandler(ServiceException.class) public R handleServiceException(ServiceException e, HttpServletRequest request) { log.error("请求地址 [{}],发生业务异常。", request.getRequestURI(), e); @@ -201,7 +189,6 @@ public class GlobalExceptionHandler { /** * 拦截未知的运行时异常 */ - @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ExceptionHandler(RuntimeException.class) public R handleRuntimeException(RuntimeException e, HttpServletRequest request) { log.error("请求地址 [{}],发生系统异常。", request.getRequestURI(), e); @@ -212,7 +199,6 @@ public class GlobalExceptionHandler { /** * 拦截未知的系统异常 */ - @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ExceptionHandler(Throwable.class) public R handleException(Throwable e, HttpServletRequest request) { log.error("请求地址 [{}],发生未知异常。", request.getRequestURI(), e); diff --git a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/vo/R.java b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/vo/R.java index dbebc7c1..f10189d3 100644 --- a/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/vo/R.java +++ b/continew-admin-common/src/main/java/top/charles7c/cnadmin/common/model/vo/R.java @@ -45,12 +45,12 @@ public class R implements Serializable { @Schema(description = "是否成功", example = "true") private boolean success; - /** 状态码 */ - @Schema(description = "状态码", example = "200") + /** 业务状态码 */ + @Schema(description = "业务状态码", example = "200") private int code; - /** 状态信息 */ - @Schema(description = "状态信息", example = "操作成功") + /** 业务状态信息 */ + @Schema(description = "业务状态信息", example = "操作成功") private String msg; /** 返回数据 */ diff --git a/continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/interceptor/LogInterceptor.java b/continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/interceptor/LogInterceptor.java index dea1d5d6..a49e7116 100644 --- a/continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/interceptor/LogInterceptor.java +++ b/continew-admin-monitor/src/main/java/top/charles7c/cnadmin/monitor/interceptor/LogInterceptor.java @@ -50,6 +50,7 @@ import top.charles7c.cnadmin.auth.model.request.LoginRequest; import top.charles7c.cnadmin.common.constant.StringConsts; import top.charles7c.cnadmin.common.constant.SysConsts; import top.charles7c.cnadmin.common.model.dto.LogContext; +import top.charles7c.cnadmin.common.model.vo.R; import top.charles7c.cnadmin.common.util.ExceptionUtils; import top.charles7c.cnadmin.common.util.IpUtils; import top.charles7c.cnadmin.common.util.ServletUtils; @@ -94,7 +95,6 @@ public class LogInterceptor implements HandlerInterceptor { if (null == logDO) { return; } - HandlerMethod handlerMethod = (HandlerMethod)handler; // 记录所属模块 this.logModule(logDO, handlerMethod); @@ -104,7 +104,6 @@ public class LogInterceptor implements HandlerInterceptor { this.logRequest(logDO, request); // 记录响应信息 this.logResponse(logDO, response); - // 保存系统日志 SpringUtil.getApplicationContext().publishEvent(logDO); } @@ -126,32 +125,30 @@ public class LogInterceptor implements HandlerInterceptor { */ private LogDO logElapsedTimeAndException() { LogContext logContext = LogContextHolder.get(); + if (null == logContext) { + return null; + } try { - if (null != logContext) { - LogDO logDO = new LogDO(); - logDO.setCreateTime(logContext.getCreateTime()); - logDO - .setElapsedTime(System.currentTimeMillis() - LocalDateTimeUtil.toEpochMilli(logDO.getCreateTime())); - logDO.setStatus(LogStatusEnum.SUCCESS); - - // 记录错误信息(非未知异常不记录异常详情,只记录错误信息) - String errorMsg = logContext.getErrorMsg(); - if (StrUtil.isNotBlank(errorMsg)) { - logDO.setStatus(LogStatusEnum.FAILURE); - logDO.setErrorMsg(errorMsg); - } - // 记录异常详情 - Throwable exception = logContext.getException(); - if (null != exception) { - logDO.setStatus(LogStatusEnum.FAILURE); - logDO.setExceptionDetail(ExceptionUtil.stacktraceToString(exception, -1)); - } - return logDO; + LogDO logDO = new LogDO(); + logDO.setCreateTime(logContext.getCreateTime()); + logDO.setElapsedTime(System.currentTimeMillis() - LocalDateTimeUtil.toEpochMilli(logDO.getCreateTime())); + logDO.setStatus(LogStatusEnum.SUCCESS); + // 记录错误信息(非未知异常不记录异常详情,只记录错误信息) + String errorMsg = logContext.getErrorMsg(); + if (StrUtil.isNotBlank(errorMsg)) { + logDO.setStatus(LogStatusEnum.FAILURE); + logDO.setErrorMsg(errorMsg); } + // 记录异常详情 + Throwable exception = logContext.getException(); + if (null != exception) { + logDO.setStatus(LogStatusEnum.FAILURE); + logDO.setExceptionDetail(ExceptionUtil.stacktraceToString(exception, -1)); + } + return logDO; } finally { LogContextHolder.remove(); } - return null; } /** @@ -166,7 +163,6 @@ public class LogInterceptor implements HandlerInterceptor { Tag classTag = handlerMethod.getBeanType().getDeclaredAnnotation(Tag.class); Log classLog = handlerMethod.getBeanType().getDeclaredAnnotation(Log.class); Log methodLog = handlerMethod.getMethodAnnotation(Log.class); - // 例如:@Tag(name = "部门管理") -> 部门管理 // (本框架代码规范)例如:@Tag(name = "部门管理 API") -> 部门管理 if (null != classTag) { @@ -194,7 +190,6 @@ public class LogInterceptor implements HandlerInterceptor { private void logDescription(LogDO logDO, HandlerMethod handlerMethod) { Operation methodOperation = handlerMethod.getMethodAnnotation(Operation.class); Log methodLog = handlerMethod.getMethodAnnotation(Log.class); - // 例如:@Operation(summary="新增部门") -> 新增部门 if (null != methodOperation) { logDO.setDescription(StrUtil.blankToDefault(methodOperation.summary(), "请在该接口方法上指定日志描述")); @@ -245,14 +240,20 @@ public class LogInterceptor implements HandlerInterceptor { private void logResponse(LogDO logDO, HttpServletResponse response) { int status = response.getStatus(); logDO.setStatusCode(status); + logDO.setStatus(status >= HttpStatus.HTTP_BAD_REQUEST ? LogStatusEnum.FAILURE : logDO.getStatus()); logDO.setResponseHeaders(this.desensitize(ServletUtil.getHeadersMap(response))); // 响应体(不记录非 JSON 响应数据) String responseBody = this.getResponseBody(response); if (StrUtil.isNotBlank(responseBody) && JSONUtil.isTypeJSON(responseBody)) { logDO.setResponseBody(responseBody); + // 业务状态码优先级高 + try { + R result = JSONUtil.toBean(responseBody, R.class); + logDO.setStatusCode(result.getCode()); + logDO.setStatus(result.isSuccess() ? LogStatusEnum.SUCCESS : LogStatusEnum.FAILURE); + } catch (Exception ignored) { + } } - // 操作失败:>= 400 - logDO.setStatus(status >= HttpStatus.HTTP_BAD_REQUEST ? LogStatusEnum.FAILURE : logDO.getStatus()); } /** @@ -269,7 +270,6 @@ public class LogInterceptor implements HandlerInterceptor { if (CollUtil.isEmpty(waitDesensitizeData)) { return desensitizeDataStr; } - for (String desensitizeProperty : operationLogProperties.getDesensitizeFields()) { waitDesensitizeData.computeIfPresent(desensitizeProperty, (k, v) -> ENCRYPT_SYMBOL); waitDesensitizeData.computeIfPresent(desensitizeProperty.toLowerCase(), (k, v) -> ENCRYPT_SYMBOL); @@ -328,13 +328,11 @@ public class LogInterceptor implements HandlerInterceptor { if (!(handler instanceof HandlerMethod) || Boolean.FALSE.equals(operationLogProperties.getEnabled())) { return false; } - // 2、检查是否需要记录内网 IP 操作 boolean isInnerIp = IpUtils.isInnerIp(ServletUtil.getClientIP(request)); if (isInnerIp && Boolean.FALSE.equals(operationLogProperties.getIncludeInnerIp())) { return false; } - // 3、排除不需要记录系统日志的接口 HandlerMethod handlerMethod = (HandlerMethod)handler; Log methodLog = handlerMethod.getMethodAnnotation(Log.class); diff --git a/continew-admin-ui/src/utils/request.ts b/continew-admin-ui/src/utils/request.ts index dd35c8fe..17cff467 100644 --- a/continew-admin-ui/src/utils/request.ts +++ b/continew-admin-ui/src/utils/request.ts @@ -46,20 +46,10 @@ axios.interceptors.response.use( ) { return response; } - const res = response.data; if (res.success) { return res; } - messageErrorWrapper({ - content: res.msg || '网络错误', - duration: 5 * 1000, - }); - return Promise.reject(new Error(res.msg || '网络错误')); - }, - (error) => { - const { response } = error; - const res = response.data; if ([401].includes(res.code) && response.config.url !== '/auth/user/info') { modalErrorWrapper({ title: '确认退出', @@ -68,8 +58,8 @@ axios.interceptors.response.use( escToClose: false, okText: '重新登录', async onOk() { - const userStore = useLoginStore(); - await userStore.logout(); + const loginStore = useLoginStore(); + await loginStore.logout(); window.location.reload(); }, }); @@ -79,6 +69,13 @@ axios.interceptors.response.use( duration: 5 * 1000, }); } + return Promise.reject(new Error(res.msg || '网络错误')); + }, + (error) => { + messageErrorWrapper({ + content: error.msg || '网络错误', + duration: 5 * 1000, + }); return Promise.reject(error); } ); diff --git a/continew-admin-ui/src/views/monitor/log/system/index.vue b/continew-admin-ui/src/views/monitor/log/system/index.vue index c68be70f..68bd847f 100644 --- a/continew-admin-ui/src/views/monitor/log/system/index.vue +++ b/continew-admin-ui/src/views/monitor/log/system/index.vue @@ -117,7 +117,7 @@