Error handling in JwtAuthenticationFilter

This commit is contained in:
Universall 2025-02-19 12:24:13 +03:00
parent f6f3289fed
commit ac2f0c1d6d
5 changed files with 40 additions and 25 deletions

View File

@ -4,6 +4,6 @@ import lombok.Data;
@Data @Data
public class LoginRQB { public class LoginRQB {
private final String login; private String login;
private final String password; private String password;
} }

View File

@ -5,7 +5,7 @@ import lombok.Getter;
@Getter @Getter
@AllArgsConstructor @AllArgsConstructor
public class ErrorResponse { public class ErrorResponsePayload {
private int status; private int status;
private String error; private String error;
private String message; private String message;

View File

@ -18,54 +18,54 @@ import org.springframework.web.servlet.resource.NoResourceFoundException;
@RestControllerAdvice @RestControllerAdvice
public class GlobalExceptionHandler { public class GlobalExceptionHandler {
public static ResponseEntity<ErrorResponse> buildErrorResponse(Exception e, HttpStatus status, @Nullable String message) { public static ResponseEntity<ErrorResponsePayload> buildErrorResponse(Exception e, HttpStatus status, @Nullable String message) {
ErrorResponse errorResponse = new ErrorResponse( ErrorResponsePayload errorResponsePayload = new ErrorResponsePayload(
status.value(), status.value(),
status.getReasonPhrase(), status.getReasonPhrase(),
message == null ? e.getMessage() : message message == null ? e.getMessage() : message
); );
return new ResponseEntity<>(errorResponse, status); return new ResponseEntity<>(errorResponsePayload, status);
} }
@ExceptionHandler(Exception.class) @ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleException(Exception e, WebRequest request) { public ResponseEntity<ErrorResponsePayload> handleException(Exception e, WebRequest request) {
Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
logger.error("Unexpected error occurred", e); logger.error("Unexpected error occurred", e);
return buildErrorResponse(e, HttpStatus.INTERNAL_SERVER_ERROR, "Unexpected error occurred"); return buildErrorResponse(e, HttpStatus.INTERNAL_SERVER_ERROR, "Unexpected error occurred");
} }
@ExceptionHandler(BadRequestHTTPException.class) @ExceptionHandler(BadRequestHTTPException.class)
public ResponseEntity<ErrorResponse> handleBadBadRequestHTTPException(BadRequestHTTPException e, WebRequest request) { public ResponseEntity<ErrorResponsePayload> handleBadBadRequestHTTPException(BadRequestHTTPException e, WebRequest request) {
return buildErrorResponse(e, HttpStatus.BAD_REQUEST, null); return buildErrorResponse(e, HttpStatus.BAD_REQUEST, null);
} }
@ExceptionHandler(NotFoundHTTPException.class) @ExceptionHandler(NotFoundHTTPException.class)
public ResponseEntity<ErrorResponse> handleNotFoundHTTPException(NotFoundHTTPException e, WebRequest request) { public ResponseEntity<ErrorResponsePayload> handleNotFoundHTTPException(NotFoundHTTPException e, WebRequest request) {
return buildErrorResponse(e, HttpStatus.NOT_FOUND, null); return buildErrorResponse(e, HttpStatus.NOT_FOUND, null);
} }
@ExceptionHandler(AlreadyExistsHTTPException.class) @ExceptionHandler(AlreadyExistsHTTPException.class)
public ResponseEntity<ErrorResponse> handleAlreadyExistsHTTPException(AlreadyExistsHTTPException e, WebRequest request) { public ResponseEntity<ErrorResponsePayload> handleAlreadyExistsHTTPException(AlreadyExistsHTTPException e, WebRequest request) {
return buildErrorResponse(e, HttpStatus.CONFLICT, null); return buildErrorResponse(e, HttpStatus.CONFLICT, null);
} }
@ExceptionHandler(HttpMessageNotReadableException.class) @ExceptionHandler(HttpMessageNotReadableException.class)
public ResponseEntity<ErrorResponse> handleHttpMessageNotReadableException(InvalidFormatException e, WebRequest request) { public ResponseEntity<ErrorResponsePayload> handleHttpMessageNotReadableException(InvalidFormatException e, WebRequest request) {
return buildErrorResponse(e, HttpStatus.BAD_REQUEST, "Bad request payload format: failed to parse"); return buildErrorResponse(e, HttpStatus.BAD_REQUEST, "Bad request payload format: failed to parse");
} }
@ExceptionHandler(HttpRequestMethodNotSupportedException.class) @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
public ResponseEntity<ErrorResponse> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e, WebRequest request) { public ResponseEntity<ErrorResponsePayload> handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e, WebRequest request) {
return buildErrorResponse(e, HttpStatus.METHOD_NOT_ALLOWED, null); return buildErrorResponse(e, HttpStatus.METHOD_NOT_ALLOWED, null);
} }
@ExceptionHandler(UnauthorizedHTTPException.class) @ExceptionHandler(UnauthorizedHTTPException.class)
public ResponseEntity<ErrorResponse> handleUnauthorizedHTTPException(UnauthorizedHTTPException e, WebRequest request) { public ResponseEntity<ErrorResponsePayload> handleUnauthorizedHTTPException(UnauthorizedHTTPException e, WebRequest request) {
return buildErrorResponse(e, HttpStatus.UNAUTHORIZED, null); return buildErrorResponse(e, HttpStatus.UNAUTHORIZED, null);
} }
@ExceptionHandler(InternalAuthenticationServiceException.class) @ExceptionHandler(InternalAuthenticationServiceException.class)
public ResponseEntity<ErrorResponse> handleInternalAuthenticationServiceException(InternalAuthenticationServiceException e, WebRequest request) { public ResponseEntity<ErrorResponsePayload> handleInternalAuthenticationServiceException(InternalAuthenticationServiceException e, WebRequest request) {
Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class); Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
logger.error("Unexpected error occurred", e); logger.error("Unexpected error occurred", e);
@ -73,12 +73,12 @@ public class GlobalExceptionHandler {
} }
@ExceptionHandler(NoResourceFoundException.class) @ExceptionHandler(NoResourceFoundException.class)
public ResponseEntity<ErrorResponse> handleNoResourceFoundException(NoResourceFoundException e, WebRequest request) { public ResponseEntity<ErrorResponsePayload> handleNoResourceFoundException(NoResourceFoundException e, WebRequest request) {
return buildErrorResponse(e, HttpStatus.NOT_FOUND, null); return buildErrorResponse(e, HttpStatus.NOT_FOUND, null);
} }
@ExceptionHandler(ForbiddenHTTPException.class) @ExceptionHandler(ForbiddenHTTPException.class)
public ResponseEntity<ErrorResponse> handleForbiddenHTTPException(ForbiddenHTTPException e, WebRequest request) { public ResponseEntity<ErrorResponsePayload> handleForbiddenHTTPException(ForbiddenHTTPException e, WebRequest request) {
return buildErrorResponse(e, HttpStatus.FORBIDDEN, null); return buildErrorResponse(e, HttpStatus.FORBIDDEN, null);
} }
} }

View File

@ -1,17 +1,16 @@
package com.displaynone.acss.security; package com.displaynone.acss.security;
import com.displaynone.acss.components.auth.AuthComponent; 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.NotFoundHTTPException;
import com.displaynone.acss.exception.generics.UnauthorizedHTTPException; 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.FilterChain;
import jakarta.servlet.ServletException; import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.lang.NonNull; import org.springframework.lang.NonNull;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
@ -44,12 +43,13 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
UsernamePasswordAuthenticationToken authentication; UsernamePasswordAuthenticationToken authentication;
try { try {
authentication = authComponent.authenticateByAccessToken(jwt); authentication = authComponent.authenticateByAccessToken(jwt);
} catch (NotFoundHTTPException e) { } catch (NotFoundHTTPException | UnauthorizedHTTPException e) {
ResponseEntity<ErrorResponse> responseEntity = GlobalExceptionHandler.buildErrorResponse(new UnauthorizedHTTPException(e.getMessage()), HttpStatus.UNAUTHORIZED, null); GlobalUtils.writeErrorToResponse(new ErrorResponsePayload(
return; // TODO HttpStatus.UNAUTHORIZED.value(),
} catch (UnauthorizedHTTPException e) { HttpStatus.UNAUTHORIZED.getReasonPhrase(),
ResponseEntity<ErrorResponse> responseEntity = GlobalExceptionHandler.buildErrorResponse(new UnauthorizedHTTPException(e.getMessage()), HttpStatus.UNAUTHORIZED, null); e.getMessage()
return; // TODO ), response);
return;
} }
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

View File

@ -1,8 +1,14 @@
package com.displaynone.acss.utils; 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 lombok.experimental.UtilityClass;
import org.springframework.http.HttpStatus;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;
import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
@ -11,6 +17,8 @@ import java.util.stream.Collectors;
@UtilityClass @UtilityClass
public class GlobalUtils { public class GlobalUtils {
private final ObjectMapper objectMapper = new ObjectMapper();
public boolean hasAnyNullField(Object obj, @Nullable List<String> fieldsToIgnore) { public boolean hasAnyNullField(Object obj, @Nullable List<String> fieldsToIgnore) {
return Arrays.stream(obj.getClass().getDeclaredFields()) return Arrays.stream(obj.getClass().getDeclaredFields())
.filter(field -> fieldsToIgnore == null || !fieldsToIgnore.contains(field.getName())) .filter(field -> fieldsToIgnore == null || !fieldsToIgnore.contains(field.getName()))
@ -31,4 +39,11 @@ public class GlobalUtils {
public <EntityT, DtoT> List<DtoT> convertAllToDTO(Collection<EntityT> entities, EntityMapper<EntityT, DtoT> mapper) { public <EntityT, DtoT> List<DtoT> convertAllToDTO(Collection<EntityT> entities, EntityMapper<EntityT, DtoT> mapper) {
return entities.stream().map(mapper::convertToDTO).collect(Collectors.toList()); 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);
}
} }