Filter 단계에서 예외 발생 시 오류 응답 누락 트러블슈팅 - KimGyuBek/Threadly GitHub Wiki
Authentication filter에서 예외가 터지면
CustomAuthenticationEntryPoint에서 감지되지 않는 문제 발생
//SecurityConfig.java
/*VerificationFilter*/
http.addFilterBefore(verificationFilter, UsernamePasswordAuthenticationFilter .class);
/*UserStatusTypeValidationFilter*/
http.
addFilterBefore(userStatusTypeValidationFilter, VerificationFilter .class);
/*jwt authentication filter*/
http.
addFilterBefore(jwtAuthenticationFilter, UserStatusTypeValidationFilter .class);필터 실행 순서:
JwtAuthenticationFilter -> UserStatusTypeValidationFilter -> VerificationFilter ->
UsernamePasswordAuthenticationFilter -> ... -> ExceptionTranslationFilter
- 커스텀 필터가
ExceptionTranslationFilter보다 앞에 위치해있다. - 결과적으로
ExceptionTranslationFilter가 호출 되지 않아서 예외 처리가 되지 않고 있다.
ExceptionTranslationFilter가 예외를 받아서AuthenticationEntrypoint로 넘겨야 하는데, 필터 순서가 앞이라 그 구간까지 못 간다. 따라서 예외 핸들링이 되지 않고 있음.
//JwtAuthenticationFilter.java
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
try {
// ...
/*사용자 관련 오류 */
} catch (UserException e) {
UserAuthenticationException exception = new UserAuthenticationException(e.getErrorCode());
authenticationEntryPoint.commence(request, response, exception);
return;
// ...
}
}//ResponseWrapperAdvice.java
@RestControllerAdvice()
public class ResponseWrapperAdvice implements ResponseBodyAdvice<Object> {
//...
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType,
MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType,
ServerHttpRequest request, ServerHttpResponse response) {
// ...
if (body instanceof ErrorResponse) { //GlobalExceptionHandler에서 예외 감지 후 ErrorResponse로 변환 후 넘어오면 공통 응답 바디로 감싼다.
return ApiResponse.fail(((ErrorResponse) body).getErrorCode());
}
return ApiResponse.success(body);
}
}filter에서 예외가 터지면 요청이
DispatcherServlet까지 못 간다. 그래서ResponseBodyAdvice가 동작하지 않고 공통 응답 바디(ApiResponse.fail())로 감싸지 못 해 응답 형태가 달라진다.
//CustomAuthenticationEntryPoint.java
@Component
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
// ...
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
// ...
/*TokenAuthenticationException일 경우*/
if (authException instanceof TokenAuthenticationException) {
ErrorCode errorCode = ((TokenAuthenticationException) authException).getErrorCode();
response.setStatus(errorCode.getHttpStatus().value());
objectMapper.writeValue(response.getWriter(),
ApiResponse.fail(errorCode));
return;
}
}
}
CustomAuthenticationEntrypoint에서 응답 바디를 직접 만들어서 리턴


ExceptionTranslatorFilter 이전에 등록된 Filter에서 발생한 예외는 단순히 throw만 해서는 ExceptionTranslationFilter까지 도달하지 못한다.
그 결과 AuthenticationEntryPoint가 실행되지 않아 실패 응답이 내려가지 않고, @ResponseBodyAdvice 역시 적용되지 않는다.
따라서 해결책은 두 가지다:
-
필터 내부에서 직접
AuthenticationEntryPoint.commence()를 호출하고 체인을 종료한다. - 또는 가능하다면 커스텀 필터를
ExceptionTranslationFilter뒤에 등록해 예외를 위임한다.
따라서 일반 예외와 Filter 예외 모두 ApiResponse.fail()을 통해 동일한 응답 포맷을 보장할 수 있게 되었다.