JWT토큰 예외처리
AuthenticationConfig
.addFilterBefore(new JwtExceptionFilter(), JwtFilter.class)
AuthenticationConfig에서 필터를 거치기 전에 ExceptionFilter를 거치며 에러를 처리할 수 있도록 코드를 추가해준다.
JWTExceptionFilter
package com.jh.jwt.exception;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.SignatureException;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
// 발생할 수 있는 에러를 만들어 setErrorResponse로 전달
@Component
@Slf4j
public class JwtExceptionFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
try {
filterChain.doFilter(request, response);
} catch (MalformedJwtException e){
log.error("JWT Filter MalformedJwtException Exception");
setErrorResponse(response, HttpStatus.UNAUTHORIZED, e);
} catch (ExpiredJwtException e) {
log.error("JWT Filter ExpiredJwtException Exception");
setErrorResponse(response, HttpStatus.UNAUTHORIZED, e);
} catch (UnsupportedJwtException e) {
log.error("JWT Filter UnsupportedJwtException Exception");
setErrorResponse(response, HttpStatus.UNAUTHORIZED, e);
} catch (SignatureException e) {
log.error("JWT Filter SignatureException Exception");
setErrorResponse(response, HttpStatus.UNAUTHORIZED, e);
} catch (IllegalArgumentException e) {
log.error("JWT Filter IllegalArgumentException Exception");
setErrorResponse(response, HttpStatus.UNAUTHORIZED, e);
}
}
// 에러가 발생되었을 때 전달받은 에러에 맞도록 세팅 후 반환
public void setErrorResponse(HttpServletResponse response, HttpStatus status, Throwable e) {
ObjectMapper objectMapper = new ObjectMapper();
response.setStatus(status.value());
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
ErrorResponse errorResponse = new ErrorResponse("error",status, e.getMessage());
try {
response.getWriter().write(objectMapper.writeValueAsString(errorResponse));
} catch (IOException ex) {
ex.printStackTrace();
}
}
// 반환 타입 Dto
@Data
public static class ErrorResponse {
private final String status;
private final HttpStatus code;
private final String message;
}
}
JWT토큰을 사용하며 발생할 수있는 에러를 처리한다. 에러가 발생하게 되면 doFilterInternal 함수를 통해 에러가 잡히게 되고 해당 에러는 setErrorResponse를 통하여 사용자에게 전달되도록 되어있다. 이를 통해 JWT에서 발생하는 에러를 관리할 수 있다.
로직 예외처리
package com.jh.jwt.exception;
import lombok.Data;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class ApiExceptionHandler {
@ExceptionHandler(UsernameNotFoundException.class)
public ResponseEntity<Object> usernameNotFoundExceptionHandler(UsernameNotFoundException e) {
ErrorResponse errorResponse = new ErrorResponse("error", 404, e.getMessage());
return ResponseEntity.badRequest().body(errorResponse);
}
@ExceptionHandler(BadCredentialsException.class)
public ResponseEntity<Object> badCredentialsExceptionHandler(BadCredentialsException e) {
ErrorResponse errorResponse = new ErrorResponse("error", 400, e.getMessage());
return ResponseEntity.badRequest().body(errorResponse);
}
@ExceptionHandler(NotLoggedInException.class)
public ResponseEntity<Object> NotLoggedInExceptionHandler(NotLoggedInException e) {
ErrorResponse errorResponse = new ErrorResponse("error", 400, e.getMessage());
return ResponseEntity.badRequest().body(errorResponse);
}
@Data
public static class ErrorResponse {
private final String status;
private final Integer code;
private final String message;
}
}
ControllerAdvice
@ControllerAdvice는 이용하여 모든 컨트롤러에서 발생할 수 있는 예외를 잡아 처리해주는 어노테이션이다. 해당 어노테이션을 사용하여 발생할 수 있는 예외들을 관리할 수 있다.
ExceptionHandler
@ExceptionHandler를 사용하면 value로 원하는 예외를 지정하고 핸들링이 가능하다. 이는 지정한 예외 뿐 아니라 예외의 자식클래스도 모두 캐치하여 지정된 응답을 반환하게 된다.
NotLoggedInException
package com.jh.jwt.exception;
public class NotLoggedInException extends RuntimeException {
public NotLoggedInException() {
}
public NotLoggedInException(String message) {
super(message);
}
public NotLoggedInException(String message, Throwable cause) {
super(message, cause);
}
public NotLoggedInException(Throwable cause) {
super(cause);
}
}
로그인 되지 않았을 때의 에러를 Custom으로 만듬
'Spring > Server' 카테고리의 다른 글
Spring JPA + JWT로 로그인 구현하기(5) - 로그아웃 구현(Redis) (1) | 2023.10.05 |
---|---|
Spring JPA + JWT로 로그인 구현하기(4) - 인증 API 구현 (1) | 2023.10.04 |
Spring JPA + JWT로 로그인 구현하기(3) - Configuration 구현 (0) | 2023.08.18 |
Spring JPA + JWT로 로그인 구현하기(2) - 엔티티 구현 (0) | 2023.08.05 |
Spring JPA + JWT로 로그인 구현하기(1) - 기본 설정 (0) | 2023.08.04 |