Logout

스프링 시큐리티는 아래와 같은 설정으로 세션, 인증토큰, 쿠키정보를 삭제해 로그아웃시킬 수 있다

//region logout
http
    .logout()   //Post Method
    .logoutUrl("/logout")    // 로그아웃 처리 url
    .logoutSuccessUrl("/login")  // 로그아웃 성공 후 이동페이지
    .addLogoutHandler(new LogoutHandler() {  // 로그아웃 핸들러
        @Override
        public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
            HttpSession session = request.getSession();
            session.invalidate();
        }
    })
    .logoutSuccessHandler(new LogoutSuccessHandler() { // 로그아웃 성공 후 핸들러
        @Override
        public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
            response.sendRedirect("/login");
        }
    })
    .deleteCookies("JSESSIONID", "remember-me");  // 로그아웃 후 쿠키 삭제
// endregion

 

동작 플로우

 

LogoutFilter.class의 doFilter() 를 보면 config에서  addLogoutHandler, logoutSuccessHandler 에 오버라이딩한 메소드인 logout과 onLogoutSuccess를 호출하는 것을 확인 할 수 있다.

private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
        throws IOException, ServletException {
    if (requiresLogout(request, response)) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (this.logger.isDebugEnabled()) {
            this.logger.debug(LogMessage.format("Logging out [%s]", auth));
        }
        this.handler.logout(request, response, auth);
        this.logoutSuccessHandler.onLogoutSuccess(request, response, auth);
        return;
    }
    chain.doFilter(request, response);
}

 

addLogoutHandler에서 세션을 제거 해주고 있지만 이 행위를 해주지 않아도 내가 만들어준 핸들러를 빠져나온 뒤 기본으로 존재하는 핸들러에서 세션을 제거해주고 있다. 아래 코드의 this.logoutHandlers 는 핸들러 목록이다.

@Override
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
    for (LogoutHandler handler : this.logoutHandlers) {
        handler.logout(request, response, authentication);
    }
}

 

그 중에 첫번째 인덱스가 내가 만들어준 클래스명인 것을 확인할 수 있다.

 

4번째 인덱스의 SecurityContextHandler.class 의 logout() 를 보면 session이 null아니라면 제거하는 로직이 존재한다.

	@Override
	public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
		Assert.notNull(request, "HttpServletRequest required");
		if (this.invalidateHttpSession) {
			HttpSession session = request.getSession(false);
			if (session != null) {
				session.invalidate();
				if (this.logger.isDebugEnabled()) {
					this.logger.debug(LogMessage.format("Invalidated session %s", session.getId()));
				}
			}
		}
		SecurityContext context = SecurityContextHolder.getContext();
		SecurityContextHolder.clearContext();
		if (this.clearAuthentication) {
			context.setAuthentication(null);
		}
	}

 

복사했습니다!