모르지 않다는 것은 아는것과 다르다.

Spring Security

ExceptionTranslationFilter,RequestCacheAwareFilter

채마스 2022. 2. 28. 20:45

ExceptionTranslationFilter

  • AuthenticationException
    • AuthenticationEntryPoint 를 호출한다.
      • 인증정보가 없다면? -> 로그인 페이지로 이동한다.
      • 401 오류 코드를 전달한다.
    • 인증 예외가 발생하기 전의 요청 정보를 저장한다.
      • 어떤 페이지로 접근하려했을때 인증이 되지않아 로그인 페이지로 이동한다면? -> 로그인 처리가 끝난 후 다시 원래 요청 페이지로 이동한다.
      • RequestCache : 사용자의 이전 요청 정보를 세션에 저장하고 이를 꺼내 오는 캐시 메커니즘이다.
      • SavedRequest : 사용자가 요청했던 request 파라미터 값들과 그 당시의 헤더값등을 저장한다.
      • 정리하면 요청정보가 SavedRequest 에 담기고, RequestCache가 SavedRequest를 세션에 저장한다.
  • AccessDeniedException
    • 인가 예외를 처리한다.
    • AccessDeniedHandler 에서 예외를 처리한다.
  • 처리과정은 아래와 같다.

  • 먼저 요청이 마지막 필터인 FilterSecurityInterceptor 필터로 도달하고, 인증 예외가 발생하면 ExceptionTranslationFilter 가 예외를 처리한다.
  • 위의 그림에서 인증예외일 경우 바로 AuthenticationException으로 보내지는 것 같지만 사실은 그렇지 않다.
    • 먼저 AccessDeniedException으로 이동하고, Remeber me 나 익명사용자의 경우 다시 AuthenticationException으로 보내진다.
    • 편하게 AuthenticationException으로 보내진다고 생각해도 괜찮다.
  • AuthenticationException에서 AythenticationEntryPoint 로 이동하기전에 SecurityContext 값을 null 로 만드는 작업이 이루어진다.
  • 사용자의 요청정보를 DefaultSavedRequest 에 저장해서 그 객체를 다시 세션에 저장한다.
  • 만약 인가 예외만 발생한다면, AccessDeniedHandler 를 호출해서 예외를 처리한다.





코드

protected void configure(HttpSecurity http) throws Exception {

  http
        .formLogin()
        .successHanlder(new AuthenticationSuccessHandler(){
          @Override
          public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
            RequestCache requestCache = new HttpSessionRequestCache();
            SavedRequest savedRequest = requestCache.getRequest(request, response);
            String redirectUrl = savedRequest.getRedirectUrl();
            response.sendRedirect(redirectUrl);
          }
        })


  http
        .exceptionHandling()                     
        .authenticationEntryPoint(new AuthenticationEntryPoint() {
          @Overried
          public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {

            response.sendRedirect("/login");

          }

        })
        .accessDeniedHandler(new AccessDeniedHandler(){
          @Overried
          public void handler(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {

            response.sendRedirect("/denied");

          }
        })

}
  • authenticationEntryPoint, accessDeniedHandler 를 구현해 줌으로써, 인증, 인가에 대한 예외 처리를 할 수 있다.
  • DefaultSavedRequest 에 저장된 요청정보를 successHanlder 에서 사용할 수 있다.
    • 세션에서 RequestCache 를 꺼내온다.
    • RequestCache 에서 SavedRequest 를 꺼내온다.
    • SavedRequest 에서 이전 요청 url 을 꺼내온다.
    • 인증처리가 완료된 후 이전 url 로 다시 리다이렉트 시킨다.





RequestCacheAwareFilter

  • 요청 정보를 담고있는 SavedRequest 객체를 여러필터에서 계속 사용할 수 있도록 넘겨주는 역할을 한다.
  • HttpServletRequest 객체로 만들어 다음 필터로 계속 넘겨준다.




REFERENCES

  • 정수원님의 스프링 시큐리티