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
public class LoginRQB {
private final String login;
private final String password;
private String login;
private String password;
}

View File

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

View File

@ -18,54 +18,54 @@ import org.springframework.web.servlet.resource.NoResourceFoundException;
@RestControllerAdvice
public class GlobalExceptionHandler {
public static ResponseEntity<ErrorResponse> buildErrorResponse(Exception e, HttpStatus status, @Nullable String message) {
ErrorResponse errorResponse = new ErrorResponse(
public static ResponseEntity<ErrorResponsePayload> 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<ErrorResponse> handleException(Exception e, WebRequest request) {
public ResponseEntity<ErrorResponsePayload> 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<ErrorResponse> handleBadBadRequestHTTPException(BadRequestHTTPException e, WebRequest request) {
public ResponseEntity<ErrorResponsePayload> handleBadBadRequestHTTPException(BadRequestHTTPException e, WebRequest request) {
return buildErrorResponse(e, HttpStatus.BAD_REQUEST, null);
}
@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);
}
@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);
}
@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");
}
@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);
}
@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);
}
@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.error("Unexpected error occurred", e);
@ -73,12 +73,12 @@ public class GlobalExceptionHandler {
}
@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);
}
@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);
}
}

View File

@ -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<ErrorResponse> responseEntity = GlobalExceptionHandler.buildErrorResponse(new UnauthorizedHTTPException(e.getMessage()), HttpStatus.UNAUTHORIZED, null);
return; // TODO
} catch (UnauthorizedHTTPException e) {
ResponseEntity<ErrorResponse> 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));

View File

@ -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<String> fieldsToIgnore) {
return Arrays.stream(obj.getClass().getDeclaredFields())
.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) {
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);
}
}