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 |