[Spring Security] 13. DefaultLogin/LogoutPageGeneratingFilter

조성우·2024년 8월 22일

Spring Security

목록 보기
13/16
post-thumbnail

DefaultSecurityFilterChain에 기본적으로 등록되는 필터로 아홉 번째, 열 번째에 위치하는 DefaultLoginPageGeneratingFilter, DefaultLogoutPageGeneratingFilter에 대해 알아보자.



DefaultLoginPageGeneratingFilter


이 필터는 로그인 설정에 대해 GET : “/login” 경로에 기본 로그인 페이지를 응답하는 역할을 수행한다.

여러 로그인 설정에 의존되며 가장 많이 사용하는 formLogin에서는 커스텀 SecurityFilterChain 등록 시 아래와 같은 설정을 통해 사용할 수 있으며, 커스텀 로그인 페이지를 사용할 경우 제외된다.

// 기본 사용
http
        .formLogin(Customizer.withDefaults());
        
// 커스텀 하더라도 아래와 같이 loginPage() 메소드를 다루지 않으면 기본 로그인 페이지 활성
http
        .formLogin((login) -> login.loginPage("/커스텀경로"));


DefaultLoginPageGeneratingFilter 클래스


public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {

    ...
    
    private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws IOException, ServletException {

        // Error 파라미터가 있는 경우
        boolean loginError = isErrorPage(request);

        // 로그아웃 성공시
        boolean logoutSuccess = isLogoutSuccess(request);

        // 조건에 맞으면 로그인 페이지 발생 로직 실행
        if (isLoginUrlRequest(request) || loginError || logoutSuccess) {

            // 로그인 페이지 생성
            String loginPageHtml = generateLoginPageHtml(request, loginError, logoutSuccess);
            // 헤더 값 설정 및 바디 추가
            response.setContentType("text/html;charset=UTF-8");
            response.setContentLength(loginPageHtml.getBytes(StandardCharsets.UTF_8).length);
            response.getWriter().write(loginPageHtml);
            return;
        }

        // 조건이 아닌 경우 다음 필터 실행
        chain.doFilter(request, response);
    }
    
    ...
    
}

로그인 설정에 따라 generateLoginPageHtml 메소드에서 아래의 로그인 페이지 응답한다.

  • form 로그인
  • oauth2 로그인
  • saml2 로그인

왜 필터 단에서 페이지를 응답하는가?

컨트롤러와 같은 프레젠테이션 레이어가 아닌 필터 단에서 VIEW를 응답하는 이유는 시큐리티 의존성의 한계 때문이다.

시큐리티 의존성에 의해서 컨트롤러에 디폴트 페이지가 존재한다면 커스텀할 컨트롤러가 디폴트 컨트롤러를 유의하면서 구현하기 쉽지 않기 때문에 필터단에서 구현되어 있다.




DefaultLogoutPageGeneratingFilter


이 필터는 GET : “/logout” 경로에 대해 기본 로그아웃 페이지를 응답하는 역할을 수행한다.

마찬가지로 formLogin에서는 커스텀 SecurityFilterChain 등록시 아래와 같은 설정을 통해 사용할 수 있다.

// 기본 사용
http
        .formLogin(Customizer.withDefaults());


DefaultLogoutPageGeneratingFilter 클래스


public class DefaultLogoutPageGeneratingFilter extends OncePerRequestFilter {

    ...
    
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        if (this.matcher.matches(request)) {
            renderLogout(request, response);
        }
        else {
            if (logger.isTraceEnabled()) {
                logger.trace(LogMessage.format("Did not render default logout page since request did not match [%s]",
                        this.matcher));
            }
            filterChain.doFilter(request, response);
        }
    }

    ...
    
}

※ 페이지를 생성하는 부분을 보면, 성능을 올리기 위해 StringBuilder를 사용한 것을 알 수 있다.

0개의 댓글