기본적으로 나의 구성
>> JwtAuthenticationFilter 이후, JwtLoginFilter 를 둠.
>> Authentication 을 한다가 더 큰 범주이니 앞에 오는게 맞긴 할듯.
문제의 시작 >
LoginFilter에서 ObjectMapper 에 문제가 발생했는데, AuthenticationFilter 에서 doFilter에 묶인 try catch 에서 받는 모습이 확인됨.
>>>>> 이상하다? ExceptionTranslationFilter 에서 받아야 하는 것 아닌가?
https://uchupura.tistory.com/22
[스프링 시큐리티] ExceptionTranslationFilter
ExceptionTranslationFilter 필터의 경우 아래 2가지 예외를 발생시킨다. 인증 예외 (AuthenticationException) AuthenticationEntryPoint 호출 로그인 페이지 이동, 401 오류 코드 전달, SecurityContext 초기화 AuthenticationEntr
uchupura.tistory.com
확인해보면 알겠지만, ETFilter 는 단 두개의 예외만을 처리하고, 그것만을 위해 존재한다.
AuthenticationException 과 AccessDeniedException. 나는 일단 Security 단에서 Access, 인가 관련해서는 하나도 건드리지 않고, 오직 Security 에 맡기고 있다. 권한쪽만 잘 연동해두고, 형성한 Authentication 객체를 SecurityContextHolder 안에만 잘 넣어주면 되기 때문이다.
그래서 ETFilter 에서 받지 못하는 것은 이해하였다.
자 내 AFilter 코드를 보면 다음과 같다.
try{
// Do your Authentication
filterChain.doFilter(request, response);
}catch(Exception e){
// Parse Exception
}
여기서 doFilter 는 다음 필터로 넘어가란 것인데, 이 이후에 발생하는 LoginFilter 에서 에러가 발생한 것이다.
그러므로 doFilter 중 에러가 발생했으므로 어찌보면 당연히 catch 로 가야 하는 것이다.
(doFilter 이후 다시 쭉 올라오나?????????????????????)
근데 문득 의문이 들었다. 그렇다면 ........... 만약 catch 로 잡아주지도 않고... ExceptionTranslationFilter 도 예외를 잡아주지 않는다면, 여기서 발생하는 Exception 들은 일반 Spring 이 처리하는 에러대로 처리를 하게 되는가?
다음 포스트를 보면 일반 Spring 이 에러를 처리하는 모습을 볼 수 있다. (Spring MVC 에서) \
https://mangkyu.tistory.com/204
[Spring] 스프링의 다양한 예외 처리 방법(ExceptionHandler, ControllerAdvice 등) 완벽하게 이해하기 - (1/2)
예외 처리는 애플리케이션을 만드는데 매우 중요한 부분을 차지한다. Spring 프레임워크는 매우 다양한 에러 처리 방법을 제공하는데, 어떠한 방법들이 있고 가장 좋은 방법(Best Practice)은 무엇인
mangkyu.tistory.com
그래서 catch 를 지우고, 쭉 따라가 보았다.
...
결론부터말하자면, Security 에서 응답까지 날리면서 끝낸다. Spring MVC 로 넘어가지 않는다. OncePerRequestFilter 를 받았기 때문에 LoginFilter 에서 발생한 에러는 최종적으로 OncePerRequestFilter 가 대응하는 방식대로 대응하는 모습을 살펴볼 수 있다. OncePerRequestFilter 에서 에러가 발생했으므로 해당 에러에 대해 곧바로 Header 및 ResponseBody 를 작성하고 내보내는 모습을 확인했다.
그리고 나서 다시 try catch 를 해보니 다음과 같은 점을 알 수 있었다.
- 사실상 Login Filter 에서 발생한 에러는 thrown new Exception (여기 같은 경우는 UnrecognizedPropertyException 이였고, 이것을 쭉~ 따라 올라가보니 결국 IOException 이였음) 으로 인해서 Error 를 던진 상태고, Error 를 던졌기 때문에 해당 Filter 는 더이상 처리하지 않고 바깥 catch 문으로 던지게 된다.
- 바깥 catch 를 잡은 필터 역시 AuthenticationFilter 로 OncePerRequsetFilter 이다.
- buildErrorResponse 를 하고 결과적으로 나만의 새로운 Exception 을 던졌기 때문에, 위와는 동일한 방식으로 내가 작성한 Response 를 내보내는 것이다. 하지만 OncePerRequestFilter 가 Exception 을 받아서 처리하는 것은 똑같음. 즉, ExceptionTranslationFilter 에서도 받지 않으므로, 여기서 처리되는게 맞음.
>> 만약 AuthenticationException 을 발생시킨다면, ExceptionTranslationFilter 에서 받게 될 것이다.
>> 그렇다면 이걸 알 수 있음. 어떤 Exception 이 발생하든 ETFilter 에 가야하는지:? 까지 판단하고 다시 올라오게 되는 것 같다.
>> 하지만 그러는 것 같지 않았음. 이번에 ObjectMapper 에서 파싱하는 도중에 error 가 발생하였고, 그러던 도중 OPRFIlter 의 에러 처리 로직으로 들어갔기 때문이다.
>> 그렇다면 AuthenticationException 이 발생할때와, 다른 EXception 들이 발생할때랑 다를 것인가>???
------------------------------------------------------------------
자 위에 내용 틀렸음, LoginFilter = AbstractAuthenticationProcessinngFilter 이고, AuthFilter = OPRFilter 였음.
자, 어찌 되었던 AuthFilter 가 밖에 있고, 그 안에 LoginFilter 가 있는데, AbstractAuthenticationProcessingFilter 는 AuthenticationException 에 대해서 처리하는 로직을 함유하고 있다.
그래서 LoginFilter 에서 AuthException 외의 Exception 은 처리하지 않고 도로 밖으로 던진것 (AuthFilter 로)
>> 그래서 위와 같이 계속 OncePerRequestFilter 의 exception 로직대로 갔던 것
>> 방금처럼 AuthenticationException 을 발생시켰더니, AbstractAuthenticationProcessingFilter 에서 AuthException 을 잡고, 여기를 거쳐서 ExceptionTranslationFilter 로 던지게 된다. 그리고 거기에서 FailureHandler 로 던지게 되는 것.
>>>>>>>>>>>>>> 기가 막힌다!!!
고로 LoginFilter 내에서 AuthenticationException 들 정리해주면 되고,
밖에서 그 외 발생하는 JWT Exception 과, 그밖의 EXception 들에 대해서 정의해주면 Security Exception 들은 정말 끝나는 듯.
(Signin 은 로직이기 때문에 Auth 단이 아님)