예외 처리 및 요청 캐시 필터
SessionManagementFilter
주요 클래스
ConcurrentSessionControlAuthenticationStrategy - 현재 저장된 세션의 count를 제공한다.
ChangeSessionIdAuthenticationStrategy - 세션 고정 보호를 위해 세션ID를 교체한다.
RegisterSessionAuthenticationStrategy - 변경된 세션ID를 등록한다.
ConcurrentSessionFilter
코드로 플로우 확인
첫번째 로그인
아래와 max 세션 수는 1개로 진행하고 초과하는 세션의 사용자를 차단하는 정책으로 설정하고 진행합니다.
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated();
http
.formLogin();
http.sessionManagement()
.maximumSessions(1)
.maxSessionsPreventsLogin(true);
return http.build();
}
로그인을 시도하면 ConcurrentSessionControlAuthenticationStrategy.java의 onAuthentication() 를 보면, (1) maximumSessions를 1로 주었고 (2) 처음 로그인이기 때문에 0 이다. 그리고 (3) if문의 의해 리턴된다.
다음에 AbstractSessionFixationProtectionStrategy.java에서 세션ID를 교체하고 있다.
마지막으로 SessionRegistryImpl.java 에서 (1) 세션을 등록해주는 걸 확인 할 수 있다. 여기 까지 오면 첫번째 로그인에 성공한다.
두번째 로그인
다른 브라우저로 로그인을 시도하면 현재 세션수와 max세션수가 동일 한다.
위 처럼 현재 세션수와 max세션수가 동일하면 allowableSessionsExceeded()가 호출 되는데 여기서 maxSessionsPreventsLogin()에 어떤 값을 줬는지에 따라 (1)이 실행될지 (2)가 실행될지가 결정된다.
true일경우 (1) 가 실행되어 아래 행위가 일어난다.
maxSessionsPreventsLogin(false) 로그인
앞과정은 건너뛰고 두번째로그인이 성공하면 아래와 같이 구문이 실행되어 이전세션 사용자의 세션을 끊어버린다.
그 이후 기존 세션이 다시 자원에 접근하게되면 (1) 에서 현재 접근한 세션의 정보를 불러오고 (2) 세션이 끊혔다면 (3) 로그아웃시켜서 맨아래 이미지의 문구를 확인할 수 있다.