@RestControllerAdvice | @ControllerAdvice는 기본적으로 모든 controller에게 적용되는 Advice이므로 Filter단에서 발생한 예외는 핸들링 해주지 못한다.
따라서 예외 발생이 예상되는 Filter의 상위에 예외를 핸들링하는 Filter를 만들어서 Filter Chain에 등록해줘야 한다.
public class JWTExceptionFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
try {
filterChain.doFilter(request, response); // 다음 필터에서 예외 발생시 catch 해준다.
} catch (AccessTokenExpiredException | InvalidLoginTokenException exception) {
setExceptionResponse(response, exception);
}
}
private void setExceptionResponse(HttpServletResponse response, CustomException exception) throws IOException {
ObjectMapper mapper = new ObjectMapper();
response.setStatus(exception.getStatusCode().value());
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
ExceptionResponse exceptionResponse = new ExceptionResponse(exception.getCode(), exception.getMessage());
String jsonResponse = mapper.writeValueAsString(exceptionResponse);
response.getWriter().write(jsonResponse);
}
}
@Slf4j
public class JWTFilter extends OncePerRequestFilter {
private final JWTUtil jwtUtil;
public JWTFilter(JWTUtil jwtUtil) {
this.jwtUtil = jwtUtil;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String accessToken = request.getHeader("access");
String path = request.getServletPath();
String method = request.getMethod();
if (accessToken == null) {
if (isNotPostAuth(path, method)) {
filterChain.doFilter(request, response);
} else {
log.debug("access token empty");
throw new InvalidLoginTokenException(4, "This is Invalid Token. Try logging in again", HttpStatus.UNAUTHORIZED);
}
return;
}
try {
jwtUtil.isExpired(accessToken);
} catch (ExpiredJwtException e) {
if(isNotPostAuth(path, method)) {
throw new AccessTokenExpiredException(6, "Access Token Expired", HttpStatus.UNAUTHORIZED);
}
else{
filterChain.doFilter(request, response);
}
return;
}
String category = jwtUtil.getCategory(accessToken);
if(!category.equals("access")) {
log.debug("invalid access token");
throw new InvalidLoginTokenException(4, "This is Invalid Token. Try logging in again", HttpStatus.UNAUTHORIZED);
}
String username = jwtUtil.getUsername(accessToken);
String role = jwtUtil.getRole(accessToken);
UserAuthDto userAuthDto = new UserAuthDto(username, role);
CustomUserDetails customOAuth2User = new CustomUserDetails(userAuthDto);
Authentication authToken = new UsernamePasswordAuthenticationToken(customOAuth2User, null, customOAuth2User.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authToken);
filterChain.doFilter(request, response);
}
private boolean isNotPostAuth(String path, String method){
return !path.equals("/auth") || !method.equals("POST");
}
}
http
.addFilterBefore(new JWTExceptionFilter(), JWTFilter.class);
'Spring Boot' 카테고리의 다른 글
Spring Boot jackson (0) | 2024.07.21 |
---|---|
Spring Boot 직렬화 필터링 fear. JSON (0) | 2024.07.14 |
Spring Boot - restful api (0) | 2024.06.26 |
Spring Boot - 비동기 처리 (0) | 2024.06.25 |
Spring Boot - RabbitMQ (0) | 2024.06.25 |