ExceptionTranslationFilter (인증과 인가의 예외 처리)
- AuthenticationException
- 인증 예외 처리
- AuthenticationEntryPoint 호출
- 로그인 페이지로 이동하고, 401 오류 코드를 전달한다.
- 인증 예외가 발생하기 전의 요청 정보를 저장한다
- RequestCache - 사용자의 이전 요청 정보를 세션에 저장하고 이를 꺼내 오는 캐시 메커니즘
- SaveRequest - 사용자가 요청했던 request 파라미터 값들, 그 당시의 헤더값들 등이 저장되어있다.
- RequestCache - 사용자의 이전 요청 정보를 세션에 저장하고 이를 꺼내 오는 캐시 메커니즘
- AuthenticationEntryPoint 호출
- 인증 예외 처리
- AccessDeniedException
- 인가 예외 처리
- AccessDeniedHandler 에서 예외를 처리한다.
- 인가 예외 처리
이 두가지의 예외를 누가? 누가 담당하고 발생시키는 것일까? 그 필터는 바로 FilterSecurityInterceptor 라는 스프링 보안 필터 중 가장 마지막을 담당하고 있는 필터이다. 이 필터 바로 앞에 있는 필터가 바로 ExceptionTranslationFilter이다.
그렇다면 스프링 시큐리티에서 일어나는 예외처리는 어떻게 진행되는 것일까?
인증 예외 처리
- 유저가 인증을 받지 않고 요청을 한다. 그렇다면 필터중 가장 마지막에 위치한 FilterSecurityInterceptor 라는 필터가 해당 요청을 잡아채게 되고 현 사용자는 인증을 받지 않았다는것을 확인했다. ( 인증 예외 발생 )
※근데 특이하게 인증 예외가 아닌 인가예외로 간다. 왜냐하면 이는 익명사용자라고 판단하기 때문이다. - 그러면 FilterSecurityInterceptor 는 ExceptionTranslationFilter 에게 예외처리를 부탁하게 되고 인가 예외로써 AccessDeniedException이 작동하게 된다.
※여기서 위에 글에선 AccessDeniedHandler 로 간다고 했는데 사용자가 익명이거나 rememberMe 역할이라면 처리를 하는 곳은 AuthenticationException 이다. - 그 후 두가지의 역할을 하게 되는데
- AuthenticationEntryPoint로 보내 예외처리를 하고 로그인 페이지로 보낸다 이때 익명의 사용자 혹은 rememberMe사용자는 SecurityContext에서 객체를 null로 만들고 보낸다
- Interceptor에 걸린 요청 인증이 안되어있는 상태로 하는 요청을 저장하는데 DefaultSavedRequest객체 안에 저장이 되고 이 객체는 세션안에 저장된다. 그리고 그 세션을 HttpSessionRequestCache안에 저장하게 된다.
인가 예외 처리
- 인가 예외로 처리가 되면 ExceptionTranslationFilter가 AccessDeniedException을 호출하고 AccessDeniedHandler를 호출하여 인가 오류 페이지로 전송한다.
시큐리티가 제공하는 ExceptionTranslationFilter 는 어떻게 적용 할 수 있을까?
이런식으로 설정할 수 있다.
authenticationEntryPoint의 commence 메소드를 통해 인증을 실패했을때 처리를 진행하고
accessDeniedHandler의 handle메소드를 통해 인가 예외 발생을 처리하게 되는것이다.
응? 그럼 아까 주구장창 말했던 cache를 저장해서 로그인 수행하면 저장되었던 내용 다시 불러온다는건 어떻게 된거야??
그건 로그인을 다시 했을때 성공하면 준다는것이다. 즉, LoginSuccessHandler 가 처리한다는 뜻이다.
바로 이렇게 되는것이다. 세션에 원래 접근하려 했던 정보가 저장되어 있고 여기서 꺼내와서 savedRequest안에 사용자가 원래 가고자 했던 요청 정보를 저장하는 것이다.
그렇다면 사용자가 이전에 요청했던 내용들을 저장하는 행위는 어디서 하는것일까?
전체적인 필터의 흐름이다. 여기서 중점으로 봐야 할것은 7번과 8번의 필터이다.
여기서 7번 RequestCacheAwareFilter 라는 것이 우리가 인증 처리를 하지 않고 데이터에 접근하면서 생긴 로그인창이 있다면 기존에 요청 정보들을 저장하는 역할을 한다. 그것을 8번인 SecurityContextHolderAwareRequestFilter에서 꺼내쓰는것이다.
정리
시큐리티는 인증과 인가를 통해 진행을 한다고 봐도 무방하고 코드의 예외처리는 매우 중요하다 그래서 시큐리티에서도 인증과 인가에 대한 예외처리를 담당하는 filter는 두가지로 인증이 다를때 하나 인가가 다를때 하나 이렇게 사용된다
나는 여기서 인증을 하기 전 마지막으로 했던 요청을 저장해두었다 다시 불러내는 역할을 꼭 기억해 둘것이다. 사용하기 너무 좋은 역할이다.
'Spring > 👨💻 SpringSecurity' 카테고리의 다른 글
JWT (0) | 2023.07.11 |
---|---|
UsernamePasswordAuthenticationFilter ( feat. FormLogin ) (0) | 2023.06.27 |
권한 설정 (0) | 2023.06.26 |
AnonymousAuthenticationFilter (0) | 2023.06.26 |
RememberMeAuthenticationFilter (0) | 2023.06.26 |