👨👩👧👦 Project/📺 KIOSEK
JwtFilter에서 예외 발생시 JwtAuthenticationEntryPoint로 이어지지 않는 문제
DevPoong
2022. 11. 25. 01:31
1. 문제 상황
JwtTokenFilter를 UsernamePasswordAuthenticationFilter 이전에 끼워 넣고 실행하였는데 필터가 두 번 호출되고 동작이 꼬여버리는 상황이 발생했다.
(1) JwtTokenFilter.java
@Component
@RequiredArgsConstructor
public class JwtTokenFilter extends OncePerRequestFilter {
private final JwtTokenProvider jwtTokenProvider;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
try{
String jwt = resolveToken(request, AUTHORIZATION_HEADER);
if (jwt != null && jwtTokenProvider.validateToken(jwt)) {
Authentication authentication = jwtTokenProvider.getAuthentication(jwt);
SecurityContextHolder.getContext().setAuthentication(authentication);
....
}
} catch(TokenNotPassedException e) {
request.setAttribute("exception", e);
log.info("catch token not passed exception");
} catch (TokenNotBearerException e) {
request.setAttribute("exception", e);
log.info("TokenNotBearerException");
} catch (SignatureException e) {
request.setAttribute("exception", e);
log.info("SignatureException");
} catch (MalformedJwtException e) {
request.setAttribute("exception", e);
log.info("MalformedJwtException");
} catch (ExpiredJwtException e) {
request.setAttribute("exception", e);
log.info("ExpiredJwtException");
} catch (UnsupportedJwtException e) {
request.setAttribute("exception", e);
log.info("UnsupportedJwtException");
} catch (JwtException | IllegalArgumentException e) {
request.setAttribute("exception", e);
log.info("JwtException | IllegalArgumentException");
}
filterChain.doFilter(request, response);
}
...
}
(2) SecurityConfig
public class SecurityConfig {
private final JwtTokenProvider jwtTokenProvider;
private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
...
....
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
.authenticationEntryPoint(jwtAuthenticationEntryPoint) // 인증 실패시 오류 처리
.accessDeniedHandler(jwtAccessDeniedHandler) // 권한 부족시 오류 처리
.and()
.apply(jwtTokenFilterConfig)
...
.addFilterBefore(new JwtTokenFilter(jwtTokenProvider, ..), UsernamePasswordAuthenticationFilter.class)
.build();
}
}
2. 문제 해결
JwtTokenFilter에 생각 없이 @Component를 달고 SecurityConfig에서 new로 다시 생성해서 설정한 것이 문제였다.
@Component로 인해 어플리케이션 실행 시 필터에 자동 등록되었고 내가 한 번 더 생성해 버려서 꼬여버린 것이다.
결론
JwtTokenFilter에서 @Component를 삭제하면 된다!
정말 사소한 것이지만 중요한 부분을 놓치는 바람에 문제가 커져서 원인을 파악하는데만 하루종일 걸렸다..
이런 실수를 또 다시 하지 않기 위해 기록한다..