错误码梳理
This commit is contained in:
@@ -3,9 +3,13 @@ package com.cisd.tms.common.enums;
|
||||
public enum ErrorCode {
|
||||
BAD_REQUEST(400, "bad request"),
|
||||
UNAUTHORIZED(4010, "unauthorized"),
|
||||
SESSION_INVALID(4011, "session invalid"),
|
||||
FORBIDDEN(4030, "forbidden"),
|
||||
VALIDATE_FAILED(4001, "parameter validation failed"),
|
||||
CONFLICT(4090, "conflict"),
|
||||
BIZ_ERROR(5001, "business exception"),
|
||||
CRYPTO_CARD_ERROR(5201, "crypto card adapter error"),
|
||||
SERVICE_UNAVAILABLE(5030, "service unavailable"),
|
||||
INTERNAL_ERROR(5000, "internal server error");
|
||||
|
||||
private final int code;
|
||||
|
||||
@@ -8,6 +8,8 @@ import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
@@ -20,7 +22,7 @@ public class GlobalExceptionHandler {
|
||||
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
|
||||
|
||||
@ExceptionHandler(MethodArgumentNotValidException.class)
|
||||
public ApiResponse<Void> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpServletRequest request) {
|
||||
public ResponseEntity<ApiResponse<Void>> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpServletRequest request) {
|
||||
String msg = ex.getBindingResult().getAllErrors().stream()
|
||||
.findFirst()
|
||||
.map(error -> {
|
||||
@@ -30,53 +32,84 @@ public class GlobalExceptionHandler {
|
||||
return error.getDefaultMessage();
|
||||
})
|
||||
.orElse(ErrorCode.VALIDATE_FAILED.getMessage());
|
||||
return ApiResponse.fail(ErrorCode.VALIDATE_FAILED.getCode(), msg).withPath(request.getRequestURI());
|
||||
return response(HttpStatus.BAD_REQUEST, ApiResponse.fail(ErrorCode.VALIDATE_FAILED.getCode(), msg).withPath(request.getRequestURI()));
|
||||
}
|
||||
|
||||
@ExceptionHandler(ConstraintViolationException.class)
|
||||
public ApiResponse<Void> handleConstraintViolation(ConstraintViolationException ex, HttpServletRequest request) {
|
||||
return ApiResponse.fail(ErrorCode.VALIDATE_FAILED.getCode(), ex.getMessage()).withPath(request.getRequestURI());
|
||||
public ResponseEntity<ApiResponse<Void>> handleConstraintViolation(ConstraintViolationException ex, HttpServletRequest request) {
|
||||
return response(HttpStatus.BAD_REQUEST,
|
||||
ApiResponse.fail(ErrorCode.VALIDATE_FAILED.getCode(), ex.getMessage()).withPath(request.getRequestURI()));
|
||||
}
|
||||
|
||||
@ExceptionHandler(BizException.class)
|
||||
public ApiResponse<Void> handleBizException(BizException ex, HttpServletRequest request) {
|
||||
return ApiResponse.fail(ex.getCode(), ex.getMessage()).withPath(request.getRequestURI());
|
||||
public ResponseEntity<ApiResponse<Void>> handleBizException(BizException ex, HttpServletRequest request) {
|
||||
return response(resolveHttpStatus(ex.getCode()),
|
||||
ApiResponse.fail(ex.getCode(), ex.getMessage()).withPath(request.getRequestURI()));
|
||||
}
|
||||
|
||||
@ExceptionHandler(IllegalArgumentException.class)
|
||||
public ApiResponse<Void> handleIllegalArgument(IllegalArgumentException ex, HttpServletRequest request) {
|
||||
return ApiResponse.fail(ErrorCode.VALIDATE_FAILED.getCode(), ex.getMessage()).withPath(request.getRequestURI());
|
||||
public ResponseEntity<ApiResponse<Void>> handleIllegalArgument(IllegalArgumentException ex, HttpServletRequest request) {
|
||||
return response(HttpStatus.BAD_REQUEST,
|
||||
ApiResponse.fail(ErrorCode.VALIDATE_FAILED.getCode(), ex.getMessage()).withPath(request.getRequestURI()));
|
||||
}
|
||||
|
||||
@ExceptionHandler(MaxUploadSizeExceededException.class)
|
||||
public ApiResponse<Void> handleMaxUploadSizeExceeded(MaxUploadSizeExceededException ex, HttpServletRequest request) {
|
||||
return ApiResponse.fail(ErrorCode.VALIDATE_FAILED.getCode(), "upload file size exceeds limit")
|
||||
.withPath(request.getRequestURI());
|
||||
public ResponseEntity<ApiResponse<Void>> handleMaxUploadSizeExceeded(MaxUploadSizeExceededException ex, HttpServletRequest request) {
|
||||
return response(HttpStatus.BAD_REQUEST, ApiResponse.fail(ErrorCode.VALIDATE_FAILED.getCode(), "upload file size exceeds limit")
|
||||
.withPath(request.getRequestURI()));
|
||||
}
|
||||
|
||||
@ExceptionHandler(MultipartException.class)
|
||||
public ApiResponse<Void> handleMultipartException(MultipartException ex, HttpServletRequest request) {
|
||||
return ApiResponse.fail(ErrorCode.VALIDATE_FAILED.getCode(), "failed to parse multipart request")
|
||||
.withPath(request.getRequestURI());
|
||||
public ResponseEntity<ApiResponse<Void>> handleMultipartException(MultipartException ex, HttpServletRequest request) {
|
||||
return response(HttpStatus.BAD_REQUEST, ApiResponse.fail(ErrorCode.VALIDATE_FAILED.getCode(), "failed to parse multipart request")
|
||||
.withPath(request.getRequestURI()));
|
||||
}
|
||||
|
||||
@ExceptionHandler(PcieCryptoException.class)
|
||||
public ApiResponse<Void> handleCryptoCardException(PcieCryptoException ex, HttpServletRequest request) {
|
||||
return ApiResponse.fail(ErrorCode.CRYPTO_CARD_ERROR.getCode(), ex.getMessage())
|
||||
.withPath(request.getRequestURI());
|
||||
public ResponseEntity<ApiResponse<Void>> handleCryptoCardException(PcieCryptoException ex, HttpServletRequest request) {
|
||||
return response(HttpStatus.INTERNAL_SERVER_ERROR, ApiResponse.fail(ErrorCode.CRYPTO_CARD_ERROR.getCode(), ex.getMessage())
|
||||
.withPath(request.getRequestURI()));
|
||||
}
|
||||
|
||||
@ExceptionHandler(ReplayProtectionException.class)
|
||||
public ApiResponse<Void> handleReplayProtectionException(ReplayProtectionException ex, HttpServletRequest request) {
|
||||
public ResponseEntity<ApiResponse<Void>> handleReplayProtectionException(ReplayProtectionException ex, HttpServletRequest request) {
|
||||
log.warn("Replay protection failed", ex);
|
||||
return ApiResponse.fail(ErrorCode.INTERNAL_ERROR.getCode(), "replay protection unavailable")
|
||||
.withPath(request.getRequestURI());
|
||||
return response(HttpStatus.SERVICE_UNAVAILABLE,
|
||||
ApiResponse.fail(ErrorCode.SERVICE_UNAVAILABLE.getCode(), "replay protection unavailable")
|
||||
.withPath(request.getRequestURI()));
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public ApiResponse<Void> handleException(Exception ex, HttpServletRequest request) {
|
||||
public ResponseEntity<ApiResponse<Void>> handleException(Exception ex, HttpServletRequest request) {
|
||||
log.error("Unhandled exception", ex);
|
||||
return ApiResponse.fail(ErrorCode.INTERNAL_ERROR.getCode(), ErrorCode.INTERNAL_ERROR.getMessage())
|
||||
.withPath(request.getRequestURI());
|
||||
return response(HttpStatus.INTERNAL_SERVER_ERROR,
|
||||
ApiResponse.fail(ErrorCode.INTERNAL_ERROR.getCode(), ErrorCode.INTERNAL_ERROR.getMessage())
|
||||
.withPath(request.getRequestURI()));
|
||||
}
|
||||
|
||||
private ResponseEntity<ApiResponse<Void>> response(HttpStatus status, ApiResponse<Void> body) {
|
||||
return ResponseEntity.status(status).body(body);
|
||||
}
|
||||
|
||||
private HttpStatus resolveHttpStatus(int code) {
|
||||
if (code == ErrorCode.BAD_REQUEST.getCode() || code == ErrorCode.VALIDATE_FAILED.getCode()) {
|
||||
return HttpStatus.BAD_REQUEST;
|
||||
}
|
||||
if (code == ErrorCode.UNAUTHORIZED.getCode()) {
|
||||
return HttpStatus.UNAUTHORIZED;
|
||||
}
|
||||
if (code == ErrorCode.SESSION_INVALID.getCode()) {
|
||||
return HttpStatus.UNAUTHORIZED;
|
||||
}
|
||||
if (code == ErrorCode.FORBIDDEN.getCode()) {
|
||||
return HttpStatus.FORBIDDEN;
|
||||
}
|
||||
if (code == ErrorCode.CONFLICT.getCode()) {
|
||||
return HttpStatus.CONFLICT;
|
||||
}
|
||||
if (code == ErrorCode.SERVICE_UNAVAILABLE.getCode()) {
|
||||
return HttpStatus.SERVICE_UNAVAILABLE;
|
||||
}
|
||||
return HttpStatus.INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ public class InternalAuthorizationInterceptor implements HandlerInterceptor {
|
||||
HttpResponseUtil.writeJson(
|
||||
response,
|
||||
HttpServletResponse.SC_FORBIDDEN,
|
||||
ApiResponse.fail(ErrorCode.UNAUTHORIZED.getCode(), message),
|
||||
ApiResponse.fail(ErrorCode.FORBIDDEN.getCode(), message),
|
||||
objectMapper
|
||||
);
|
||||
}
|
||||
|
||||
@@ -461,9 +461,9 @@ public class AuthServiceImpl implements AuthService {
|
||||
|
||||
private AuthSessionEntity requireActiveSession(String sessionToken) {
|
||||
AuthSessionEntity session = authSessionRepository.findBySessionToken(sessionToken)
|
||||
.orElseThrow(() -> new BizException(ErrorCode.UNAUTHORIZED.getCode(), "session not found"));
|
||||
.orElseThrow(() -> new BizException(ErrorCode.SESSION_INVALID.getCode(), "session not found"));
|
||||
if (session.getLogoutAt() != null || session.getExpiresAt() == null || !session.getExpiresAt().isAfter(now())) {
|
||||
throw new BizException(ErrorCode.UNAUTHORIZED.getCode(), "session expired");
|
||||
throw new BizException(ErrorCode.SESSION_INVALID.getCode(), "session expired");
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.cisd.tms.modules.device.controller;
|
||||
|
||||
|
||||
import com.cisd.tms.common.api.ApiResponse;
|
||||
import com.cisd.tms.common.enums.ErrorCode;
|
||||
import com.cisd.tms.common.exception.BizException;
|
||||
import com.cisd.tms.modules.device.dto.network.*;
|
||||
import com.cisd.tms.modules.device.service.NetworkConfigService;
|
||||
import com.cisd.tms.modules.log.annotation.AuditedOperation;
|
||||
@@ -122,7 +124,7 @@ public class NetworkConfigController {
|
||||
String mode = networkConfigService.getBondMode(bondName);
|
||||
|
||||
if (mode == null) {
|
||||
return ApiResponse.fail(400, "未找到该连接的 Bond 模式", null);
|
||||
throw new BizException(ErrorCode.BAD_REQUEST.getCode(), "未找到该连接的 Bond 模式");
|
||||
}
|
||||
|
||||
return ApiResponse.success(mode);
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
package com.cisd.tms.modules.device.filter;
|
||||
|
||||
import com.cisd.tms.common.api.ApiResponse;
|
||||
import com.cisd.tms.common.enums.ErrorCode;
|
||||
import com.cisd.tms.common.util.HttpResponseUtil;
|
||||
import com.cisd.tms.modules.device.service.IpWhitelistService;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@@ -17,6 +21,9 @@ public class IpWhitelistFilter implements Filter {
|
||||
@Autowired
|
||||
private IpWhitelistService ipWhitelistService;
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper objectMapper;
|
||||
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
|
||||
@@ -39,9 +46,7 @@ public class IpWhitelistFilter implements Filter {
|
||||
try {
|
||||
clientIpInt = ipToInt(clientIp);
|
||||
} catch (IllegalArgumentException e) {
|
||||
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
|
||||
response.setContentType("application/json;charset=utf-8");
|
||||
response.getWriter().write("{\"code\": 403, \"msg\": \"非法的客户端 IP 格式,拒绝访问\"}");
|
||||
writeForbidden(response, "非法的客户端 IP 格式,拒绝访问");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -72,9 +77,7 @@ public class IpWhitelistFilter implements Filter {
|
||||
|
||||
// 默认拒绝
|
||||
if (!isAllowed) {
|
||||
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
|
||||
response.setContentType("application/json;charset=utf-8");
|
||||
response.getWriter().write("{\"code\": 403, \"msg\": \"非法访问:您的IP不在允许的白名单内\"}");
|
||||
writeForbidden(response, "非法访问:您的IP不在允许的白名单内");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -136,4 +139,13 @@ public class IpWhitelistFilter implements Filter {
|
||||
return result;
|
||||
}
|
||||
|
||||
private void writeForbidden(HttpServletResponse response, String message) throws IOException {
|
||||
HttpResponseUtil.writeJson(
|
||||
response,
|
||||
HttpServletResponse.SC_FORBIDDEN,
|
||||
ApiResponse.fail(ErrorCode.FORBIDDEN.getCode(), message),
|
||||
objectMapper
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.cisd.tms.modules.log.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.cisd.tms.common.api.ApiResponse;
|
||||
import com.cisd.tms.common.enums.ErrorCode;
|
||||
import com.cisd.tms.common.exception.BizException;
|
||||
import com.cisd.tms.modules.log.dto.AuditLogReviewRequest;
|
||||
import com.cisd.tms.modules.log.dto.OperationAuditLogPageRequest;
|
||||
import com.cisd.tms.modules.log.dto.OperationAuditLogPageResponse;
|
||||
@@ -50,7 +52,7 @@ public class OperationAuditController {
|
||||
|
||||
// 权限校验:仅审计管理员可操作
|
||||
if (roleObj == null || !roleObj.toString().equals("AUDIT_ADMIN")) {
|
||||
return ApiResponse.fail(403, "权限不足:仅审计管理员可执行此操作");
|
||||
throw new BizException(ErrorCode.FORBIDDEN.getCode(), "权限不足:仅审计管理员可执行此操作");
|
||||
}
|
||||
|
||||
auditorUser = roleObj.toString();
|
||||
@@ -59,4 +61,4 @@ public class OperationAuditController {
|
||||
auditService.reviewLog(logId, req, auditorUser);
|
||||
return ApiResponse.success();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,17 +51,17 @@ public class InternalApiAuthInterceptor implements HandlerInterceptor {
|
||||
|
||||
String sessionToken = extractSessionToken(request);
|
||||
if (sessionToken == null || sessionToken.isBlank()) {
|
||||
writeUnauthorized(response, "session token missing");
|
||||
writeSessionInvalid(response, "session token missing");
|
||||
return false;
|
||||
}
|
||||
|
||||
AuthSessionEntity session = authSessionRepository.findBySessionToken(sessionToken).orElse(null);
|
||||
if (session == null || session.getLogoutAt() != null) {
|
||||
writeUnauthorized(response, "session not found");
|
||||
writeSessionInvalid(response, "session not found");
|
||||
return false;
|
||||
}
|
||||
if (session.getExpiresAt() == null || !session.getExpiresAt().isAfter(now())) {
|
||||
writeUnauthorized(response, "session expired");
|
||||
writeSessionInvalid(response, "session expired");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -99,4 +99,13 @@ public class InternalApiAuthInterceptor implements HandlerInterceptor {
|
||||
objectMapper
|
||||
);
|
||||
}
|
||||
|
||||
private void writeSessionInvalid(HttpServletResponse response, String message) throws IOException {
|
||||
HttpResponseUtil.writeJson(
|
||||
response,
|
||||
HttpServletResponse.SC_UNAUTHORIZED,
|
||||
ApiResponse.fail(ErrorCode.SESSION_INVALID.getCode(), message),
|
||||
objectMapper
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,11 +69,11 @@ public class InternalApiReplayInterceptor implements HandlerInterceptor {
|
||||
try {
|
||||
ReplayCheckResult result = replayProtectionService.check(replayRequest);
|
||||
if (result.isReplayed()) {
|
||||
writeJson(response, HttpServletResponse.SC_CONFLICT, ErrorCode.UNAUTHORIZED.getCode(), "replayed nonce");
|
||||
writeJson(response, HttpServletResponse.SC_CONFLICT, ErrorCode.CONFLICT.getCode(), "replayed nonce");
|
||||
return false;
|
||||
}
|
||||
} catch (ReplayProtectionException ex) {
|
||||
writeJson(response, HttpServletResponse.SC_SERVICE_UNAVAILABLE, ErrorCode.INTERNAL_ERROR.getCode(),
|
||||
writeJson(response, HttpServletResponse.SC_SERVICE_UNAVAILABLE, ErrorCode.SERVICE_UNAVAILABLE.getCode(),
|
||||
"replay protection unavailable");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -89,11 +89,12 @@ public class OpenApiSignAuthInterceptor implements HandlerInterceptor {
|
||||
// 先完成签名校验,再占用 nonce,避免伪造请求提前消耗合法 nonce。
|
||||
ReplayCheckResult result = replayProtectionService.check(buildReplayRequest(request, appId, nonce, requestEpoch));
|
||||
if (result.isReplayed()) {
|
||||
writeUnauthorized(response, "replayed nonce");
|
||||
writeJson(response, HttpServletResponse.SC_CONFLICT, ErrorCode.CONFLICT.getCode(), "replayed nonce");
|
||||
return false;
|
||||
}
|
||||
} catch (ReplayProtectionException ex) {
|
||||
writeUnauthorized(response, "replay protection unavailable");
|
||||
writeJson(response, HttpServletResponse.SC_SERVICE_UNAVAILABLE,
|
||||
ErrorCode.SERVICE_UNAVAILABLE.getCode(), "replay protection unavailable");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -136,10 +137,14 @@ public class OpenApiSignAuthInterceptor implements HandlerInterceptor {
|
||||
}
|
||||
|
||||
private void writeUnauthorized(HttpServletResponse response, String message) throws IOException {
|
||||
writeJson(response, HttpServletResponse.SC_UNAUTHORIZED, ErrorCode.UNAUTHORIZED.getCode(), message);
|
||||
}
|
||||
|
||||
private void writeJson(HttpServletResponse response, int status, int code, String message) throws IOException {
|
||||
HttpResponseUtil.writeJson(
|
||||
response,
|
||||
HttpServletResponse.SC_UNAUTHORIZED,
|
||||
ApiResponse.fail(ErrorCode.UNAUTHORIZED.getCode(), message),
|
||||
status,
|
||||
ApiResponse.fail(code, message),
|
||||
objectMapper
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user