From ac2f0c1d6d0097f476ed0d8e56f93ab143d0237c Mon Sep 17 00:00:00 2001 From: Universall Date: Wed, 19 Feb 2025 12:24:13 +0300 Subject: [PATCH] Error handling in JwtAuthenticationFilter --- .../acss/controllers/auth/LoginRQB.java | 4 +-- ...esponse.java => ErrorResponsePayload.java} | 2 +- .../handler/GlobalExceptionHandler.java | 26 +++++++++---------- .../security/JwtAuthenticationFilter.java | 18 ++++++------- .../displaynone/acss/utils/GlobalUtils.java | 15 +++++++++++ 5 files changed, 40 insertions(+), 25 deletions(-) rename src/main/java/com/displaynone/acss/exception/{ErrorResponse.java => ErrorResponsePayload.java} (85%) diff --git a/src/main/java/com/displaynone/acss/controllers/auth/LoginRQB.java b/src/main/java/com/displaynone/acss/controllers/auth/LoginRQB.java index 06f7731..9e6f539 100644 --- a/src/main/java/com/displaynone/acss/controllers/auth/LoginRQB.java +++ b/src/main/java/com/displaynone/acss/controllers/auth/LoginRQB.java @@ -4,6 +4,6 @@ import lombok.Data; @Data public class LoginRQB { - private final String login; - private final String password; + private String login; + private String password; } diff --git a/src/main/java/com/displaynone/acss/exception/ErrorResponse.java b/src/main/java/com/displaynone/acss/exception/ErrorResponsePayload.java similarity index 85% rename from src/main/java/com/displaynone/acss/exception/ErrorResponse.java rename to src/main/java/com/displaynone/acss/exception/ErrorResponsePayload.java index f07c896..ebe6511 100644 --- a/src/main/java/com/displaynone/acss/exception/ErrorResponse.java +++ b/src/main/java/com/displaynone/acss/exception/ErrorResponsePayload.java @@ -5,7 +5,7 @@ import lombok.Getter; @Getter @AllArgsConstructor -public class ErrorResponse { +public class ErrorResponsePayload { private int status; private String error; private String message; diff --git a/src/main/java/com/displaynone/acss/exception/handler/GlobalExceptionHandler.java b/src/main/java/com/displaynone/acss/exception/handler/GlobalExceptionHandler.java index 844f3fe..1394f0b 100644 --- a/src/main/java/com/displaynone/acss/exception/handler/GlobalExceptionHandler.java +++ b/src/main/java/com/displaynone/acss/exception/handler/GlobalExceptionHandler.java @@ -18,54 +18,54 @@ import org.springframework.web.servlet.resource.NoResourceFoundException; @RestControllerAdvice public class GlobalExceptionHandler { - public static ResponseEntity buildErrorResponse(Exception e, HttpStatus status, @Nullable String message) { - ErrorResponse errorResponse = new ErrorResponse( + public static ResponseEntity buildErrorResponse(Exception e, HttpStatus status, @Nullable String message) { + ErrorResponsePayload errorResponsePayload = new ErrorResponsePayload( status.value(), status.getReasonPhrase(), message == null ? e.getMessage() : message ); - return new ResponseEntity<>(errorResponse, status); + return new ResponseEntity<>(errorResponsePayload, status); } @ExceptionHandler(Exception.class) - public ResponseEntity handleException(Exception e, WebRequest request) { + public ResponseEntity handleException(Exception e, WebRequest request) { Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); logger.error("Unexpected error occurred", e); return buildErrorResponse(e, HttpStatus.INTERNAL_SERVER_ERROR, "Unexpected error occurred"); } @ExceptionHandler(BadRequestHTTPException.class) - public ResponseEntity handleBadBadRequestHTTPException(BadRequestHTTPException e, WebRequest request) { + public ResponseEntity handleBadBadRequestHTTPException(BadRequestHTTPException e, WebRequest request) { return buildErrorResponse(e, HttpStatus.BAD_REQUEST, null); } @ExceptionHandler(NotFoundHTTPException.class) - public ResponseEntity handleNotFoundHTTPException(NotFoundHTTPException e, WebRequest request) { + public ResponseEntity handleNotFoundHTTPException(NotFoundHTTPException e, WebRequest request) { return buildErrorResponse(e, HttpStatus.NOT_FOUND, null); } @ExceptionHandler(AlreadyExistsHTTPException.class) - public ResponseEntity handleAlreadyExistsHTTPException(AlreadyExistsHTTPException e, WebRequest request) { + public ResponseEntity handleAlreadyExistsHTTPException(AlreadyExistsHTTPException e, WebRequest request) { return buildErrorResponse(e, HttpStatus.CONFLICT, null); } @ExceptionHandler(HttpMessageNotReadableException.class) - public ResponseEntity handleHttpMessageNotReadableException(InvalidFormatException e, WebRequest request) { + public ResponseEntity handleHttpMessageNotReadableException(InvalidFormatException e, WebRequest request) { return buildErrorResponse(e, HttpStatus.BAD_REQUEST, "Bad request payload format: failed to parse"); } @ExceptionHandler(HttpRequestMethodNotSupportedException.class) - public ResponseEntity handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e, WebRequest request) { + public ResponseEntity handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e, WebRequest request) { return buildErrorResponse(e, HttpStatus.METHOD_NOT_ALLOWED, null); } @ExceptionHandler(UnauthorizedHTTPException.class) - public ResponseEntity handleUnauthorizedHTTPException(UnauthorizedHTTPException e, WebRequest request) { + public ResponseEntity handleUnauthorizedHTTPException(UnauthorizedHTTPException e, WebRequest request) { return buildErrorResponse(e, HttpStatus.UNAUTHORIZED, null); } @ExceptionHandler(InternalAuthenticationServiceException.class) - public ResponseEntity handleInternalAuthenticationServiceException(InternalAuthenticationServiceException e, WebRequest request) { + public ResponseEntity handleInternalAuthenticationServiceException(InternalAuthenticationServiceException e, WebRequest request) { Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); logger.error("Unexpected error occurred", e); @@ -73,12 +73,12 @@ public class GlobalExceptionHandler { } @ExceptionHandler(NoResourceFoundException.class) - public ResponseEntity handleNoResourceFoundException(NoResourceFoundException e, WebRequest request) { + public ResponseEntity handleNoResourceFoundException(NoResourceFoundException e, WebRequest request) { return buildErrorResponse(e, HttpStatus.NOT_FOUND, null); } @ExceptionHandler(ForbiddenHTTPException.class) - public ResponseEntity handleForbiddenHTTPException(ForbiddenHTTPException e, WebRequest request) { + public ResponseEntity handleForbiddenHTTPException(ForbiddenHTTPException e, WebRequest request) { return buildErrorResponse(e, HttpStatus.FORBIDDEN, null); } } diff --git a/src/main/java/com/displaynone/acss/security/JwtAuthenticationFilter.java b/src/main/java/com/displaynone/acss/security/JwtAuthenticationFilter.java index 662672d..a5bd4a8 100644 --- a/src/main/java/com/displaynone/acss/security/JwtAuthenticationFilter.java +++ b/src/main/java/com/displaynone/acss/security/JwtAuthenticationFilter.java @@ -1,17 +1,16 @@ package com.displaynone.acss.security; import com.displaynone.acss.components.auth.AuthComponent; -import com.displaynone.acss.exception.ErrorResponse; +import com.displaynone.acss.exception.ErrorResponsePayload; import com.displaynone.acss.exception.generics.NotFoundHTTPException; import com.displaynone.acss.exception.generics.UnauthorizedHTTPException; -import com.displaynone.acss.exception.handler.GlobalExceptionHandler; +import com.displaynone.acss.utils.GlobalUtils; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.lang.NonNull; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; @@ -44,12 +43,13 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter { UsernamePasswordAuthenticationToken authentication; try { authentication = authComponent.authenticateByAccessToken(jwt); - } catch (NotFoundHTTPException e) { - ResponseEntity responseEntity = GlobalExceptionHandler.buildErrorResponse(new UnauthorizedHTTPException(e.getMessage()), HttpStatus.UNAUTHORIZED, null); - return; // TODO - } catch (UnauthorizedHTTPException e) { - ResponseEntity responseEntity = GlobalExceptionHandler.buildErrorResponse(new UnauthorizedHTTPException(e.getMessage()), HttpStatus.UNAUTHORIZED, null); - return; // TODO + } catch (NotFoundHTTPException | UnauthorizedHTTPException e) { + GlobalUtils.writeErrorToResponse(new ErrorResponsePayload( + HttpStatus.UNAUTHORIZED.value(), + HttpStatus.UNAUTHORIZED.getReasonPhrase(), + e.getMessage() + ), response); + return; } authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); diff --git a/src/main/java/com/displaynone/acss/utils/GlobalUtils.java b/src/main/java/com/displaynone/acss/utils/GlobalUtils.java index 034326f..50bf63c 100644 --- a/src/main/java/com/displaynone/acss/utils/GlobalUtils.java +++ b/src/main/java/com/displaynone/acss/utils/GlobalUtils.java @@ -1,8 +1,14 @@ package com.displaynone.acss.utils; +import com.displaynone.acss.exception.ErrorResponsePayload; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.servlet.http.HttpServletResponse; import lombok.experimental.UtilityClass; +import org.springframework.http.HttpStatus; import org.springframework.lang.Nullable; +import java.io.IOException; import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -11,6 +17,8 @@ import java.util.stream.Collectors; @UtilityClass public class GlobalUtils { + private final ObjectMapper objectMapper = new ObjectMapper(); + public boolean hasAnyNullField(Object obj, @Nullable List fieldsToIgnore) { return Arrays.stream(obj.getClass().getDeclaredFields()) .filter(field -> fieldsToIgnore == null || !fieldsToIgnore.contains(field.getName())) @@ -31,4 +39,11 @@ public class GlobalUtils { public List convertAllToDTO(Collection entities, EntityMapper mapper) { return entities.stream().map(mapper::convertToDTO).collect(Collectors.toList()); } + + public void writeErrorToResponse(ErrorResponsePayload payload, HttpServletResponse response) throws IOException { + String jsonResponse = objectMapper.writeValueAsString(payload); + response.setStatus(payload.getStatus()); + response.setContentType("application/json"); + response.getWriter().write(jsonResponse); + } }