본문 바로가기

Language/Spring Security

SessionManagementFilter / ConcurrentSessionFilter

SessionManagementFilter

  • 요청이 시작된 이후 사용자가 인증되었는지 감지하고, 인증된 경우에는 세션 고정 보호 메커니즘을 활성화하거나 동시 다중 로그인을 확인하는 등 세션 관련 활동을 수행하기 위해 설정된 세션 인증 전략(SessionAuthenticationStrategy)을 호출하는 필터 클래스
  • 스프링 시큐리티 6 이상에서는 SessionManagementFilter가 기본적으로 설정 되지 않으며 세션관리 API 를 설정을 통해 생성 가능
    SessionManagement API를 추가해야 SessionManagementFilter가 추가

  • ChangeSessionIdAuthenticationStrategy : 세션 고정 보호 → 세션 고정 공격 방지
  • ConcurrentSessionControlAuthenticationStragtegy : 세션 만료, 인증 시도 차단
  • RegisterSessionAuthenticationStrategy : 사용자의 정보를 저장
  • SessionFixationProtectionStrategy : 세션 아이디 변경과 동일한 기능인데 분리한 것

ConcurrentSessionFilter

  • 각 요청에 대해 SessionRegistry에서 SessionInformation을 검색하고 세션이 만료로 표시되었는지 확인하고 만료로 표시된 경우 로그아웃 처리를 수행
    → 세션 무효화가 목적 → 동시 세션 제어와 밀접한 관계
  • 각 요청에 대해 SessionRegistry.refreshLastRequest(String)를 호출하여 등록된 세션들이 항상 '마지막 업데이트' 날짜/시간을 가지도록 함

흐름도

 

  1. 사용자 인증 요청 성공 → 세션 + 1
  2. 세션 허용 개수 초과 시 SessionManagementFilter가 세션을 만료를 해야할 사용자에게 session.expireNow()로 만료라고 설정(만료가 된 것은 아님)
  3. 사용자 재접속 → ConcurrentSessionFilter가 세션 만료 표시 확인
    • 만료 (Y) ⇒ ConcurrentSessionFilter가 실제로 로그 아웃 처리
    • 만료 X (N) ⇒ ConcurrentSessionFilter가 세션의 날짜/시간 업데이트

시퀀스 다이어그램

  • 사용자 2명이 동일한 계정으로 로그인한다고 가정 / 최대 허용 세션 개수 1
  • UsernamePasswordAuthenticationFilter
    • 사용자의 username, password를 검사하여 인증
  • ConcurrentSessionFilter
    • user1의 expired 상태를 확인 → true → 로그아웃 & 세션 만료 문구 응답
  • RegisterSessionAuthenticationStrategy
    • 세션 정보를 등록하는 클래스
  • ChangeSessionIdAuthenticationStrategy
    • Session 고정 보호를 위해 SessionID를 변경해주는 역할을 하는 클래스
  • ConcurrentSessionControlAuthenticationStrategy
    • 동시적 세션 제어를 관리하는 클래스

정리

  • 동시적 세션 제어를 하기 위해서는 반드시 HttpSecurity의 sessionManagemnet() 메서드 안에서 maximumSessions(n)의 설정 필요
    → 세션이 무한대면 제어를 하는 것이 말이 되지 않음
  • 동시적 세션을 제어 하는데에 SessionManagementFilter가 중요한 역할을 하고, HttpSecurity.sessionManagement()를 사용 시 SessionManagementFilter가 생성
  1. 사용자 로그인 시 AuthenticationFilter에서 인증 처리
  2. 인증 성공 시 ConcurrentSessionFilter에서 Session 만료 여부 확인
  3. SessionManagementFilter에서 세션 허용 개수 확인
    → 초과 시 세션을 만료해야 하는 사용자에게 session.expireNow()로 만료를 표시(실제로 세션 만료가 되지는 않음)
  4. 세션 숫자 1개 추가
  5. 세션이 만료된 사용자 접속 시 ConcurrentSessionFilter에서 session.isExpire()를 사용하여 세션 만료 확인
  6. 세션이 만료되었을 경우 로그아웃 처리(실질적 세션 만료)와 세션 만료 내용 응답