LogoutFilter
LogoutFilter 목적
- 이 필터는
DefaultSecurityFilterChain에 기본적으로 등록되는 필터로 일곱 번째에 위치한다. - 이 필터가 등록되는 목적은 인증 후 생성되는 사용자 식별 정보에 대해 로그아웃 핸들러를 돌며 로그아웃을 수행하는 필터이다.
- 기본적으로 세션 방식에 대한 로그아웃 설정이 되어 있기 때문에 JWT 방식이나 추가할 로직이 많을 경우 커스텀해야 한다.
- 커스텀
SecurityFilterChain을 생성해도 기본적으로 등록되며, 비활성화하려면 아래와 같이 설정할 수 있다.
Java
http.logout((logout) ->logout.disable());
- 커스텀한
LogoutFilter가 있는 경우 기본 제공되는 필터를 비활성화 처리 해야 한다.
LogoutFilter 클래스
Java
public class LogoutFilter extends GenericFilterBean {
}
주요 로직 : doFilter
Java
private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 로그아웃 요청인지 확인
if (requiresLogout(request, response)) {
Authentication auth = this.securityContextHolderStrategy.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);
}
handler 는?
CompositeLogoutHandler클래스에서 등록되어 있는 모든 로그아웃 핸들러는 순회하면서 로그아웃을 수행한다.
Java
public final class CompositeLogoutHandler implements LogoutHandler {
private final List<LogoutHandler> logoutHandlers;
public CompositeLogoutHandler(LogoutHandler... logoutHandlers) {
Assert.notEmpty(logoutHandlers, "LogoutHandlers are required");
this.logoutHandlers = Arrays.asList(logoutHandlers);
}
public CompositeLogoutHandler(List<LogoutHandler> logoutHandlers) {
Assert.notEmpty(logoutHandlers, "LogoutHandlers are required");
this.logoutHandlers = logoutHandlers;
}
@Override
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
for (LogoutHandler handler : this.logoutHandlers) {
handler.logout(request, response, authentication);
}
}
}
Logout 핸들러
Java
public interface LogoutHandler {
void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication);
}
- 로그아웃 핸들러들은 위와 같은 LogoutHandler 인터페이스를 구현한 구현 클래스들로 이루어져 있으며 커스텀 핸들러 생성시에도 위 인터페이스 기반으로 작성해야 한다.
기본 제공 핸들러
SecurityContextLogoutHandler:SecurityContextHolder에 존재하는SecurityContext초기화CookieClearingLogoutHandler:SecurityFilterChain의 logout 메소드에서 지정한 쿠키 삭제HeaderWriterLogoutHandler: 클라이언트에게 반환될 헤더 조작LogoutSuccessEventPublishingLogoutHandler: 로그아웃 성공 후 특정 이벤트 실행
커스텀 Logout 핸들러
- 기본적으로 제공하지만 등록되어 있지 않거나, 커스텀해서 만든 핸들러를 등록하는 방법은 아래 메소드를 활용한다.
Java
CookieClearingLogoutHandler cookies = new CookieClearingLogoutHandler("our-custom-cookie");
http.logout((logout) ->logout.addLogoutHandler(cookies));
Logout 성공 핸들러
- 로그아웃이 성공한 뒤 URL 리디렉션과 같은 특정 작업을 수행하기 위한 핸들러로 위의 Logout 핸들러와 다르다.
Java
public interface LogoutSuccessHandler {
void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException, ServletException;
}