[ 정수원 스프링 시큐리티 #1 ] 스프링 시큐리티 기본 API & Filter 이해 (5)

김수호·2024년 3월 8일
0
post-thumbnail

지난 포스팅에 이어, 이번 포스팅에서는 10) 의 내용을 정리한다.

👉 목차는 다음과 같다.

1) 인증 API - 프로젝트 구성 및 의존성 추가
2) 인증 API - 사용자 정의 보안 기능 구현
3) 인증 API - Form Login 인증
4) 인증 API - Form Login 인증 필터 : UsernamePasswordAuthenticationFilter
5) 인증 API - Logout 처리, LogoutFilter
6) 인증 API - Remember Me 인증
7) 인증 API - Remember Me 인증 필터 : RememberMeAuthenticationFilter
8) 인증 API - 익명사용자 인증 필터 : AnonymousAuthenticationFilter
9) 인증 API - 동시 세션 제어, 세션 고정 보호, 세션 정책
10) 인증 API - 세션 제어 필터 : SessionManagementFilter, ConcurrentSessionFilter
11) 인가 API - 권한 설정 및 표현식
12) 인증/인가 API - 예외 처리 및 요청 캐시 필터 : ExceptionTranslationFilter, RequestCacheAwareFilter
13) Form 인증 - 사이트 간 요청 위조 : CSRF, CsrfFilter

바로 하나씩 확인해보자.


10) 세션 제어 필터 : SessionManagementFilter, ConcurrentSessionFilter

✔️ SessionManagementFilter

  • 1) 세션 관리
    • 인증 시 사용자의 세션정보를 등록, 조회, 삭제 등의 세션 이력을 관리
  • 2) 동시적 세션 제어
    • 동일 계정으로 접속이 허용되는 최대 세션수를 제한
  • 3) 세션 고정 보호
    • 인증할 때 마다 세션쿠키를 새로 발급하여 공격자의 쿠키 조작을 방지
  • 4) 세션 생성 정책
    • Always, If_Required, Never, Stateless
  • 참고) SessionManagementFilter 의 핵심적인 역할인 위 1) ~ 4) 내용들은 이전 내용에서 SessionManagement API를 설정하고, 그와 관련된 기능들을 직접 코드로 작성해서 테스트 해보았다.

✔️ ConcurrentSessionFilter

  • 매 요청 마다 현재 사용자의 세션 만료 여부를 체크
  • 세션이 만료되었을 경우 즉시 만료 처리
  • session.isExpired() == true 인 경우
    • 로그아웃 처리
    • 즉시 오류 페이지 응답 ( "This session has been expired" )
  • 참고) ConcurrentSessionFilterSessionManagementFilter 는 동시적 세션 제어 처리를 위해 ( expired 값으로 ) 서로 연계해서 처리한다.

그러면 ConcurrentSessionFilterSessionManagementFilter 가 동시적 세션 제어 처리를 할 때, 어떻게 연계를 해서 처리하는지 흐름을 살펴보자.

  • 참고)
    • 현재 사용자가 로그인을 시도한다. 참고로 다음과 같은 상황이라고 가정하자.
      • 1) 현재 사용자의 인증 계정과 이미 동일한 계정으로 누군가가 인증을 시도했고, 세션이 생성된 상태이다.
      • 2) 최대 세션 허용 가능 개수를 1개로 설정했다.
      • 3) 동시 세션 제어로 이전 사용자의 세션을 만료시키는 전략을 사용한다.
    • 그러면, 최대 세션 허용 개수가 초과되었으므로 SessionManagementFilter 는 이전 사용자의 세션을 만료로 설정한다. ( session.expireNow() )
      • 참고) session.expireNow() 에서는 expired 값을 true로 변경한다.
    • 이후, 이전 사용자가 다시 서버에 접근을 시도한다.
    • 매 요청마다 사용자의 세션 만료 여부를 체크하는 ConcurrentSessionFiltersession.isExpired() 를 통해 세션이 만료로 설정되었는지 여부를 확인하고, 그 값이 true인 경우, 즉시 로그아웃 처리를 하고 오류페이지를 응답한다.
      • 참고) session.isExpired()는 expired 값을 조회한다.

 

그러면 ConcurrentSessionFilterSessionManagementFilter 가 인증부터 시작해서, 각각의 필터와 그 필터들이 가지고 있는 클래스들을 통해, 세션 관련된 전반적인 처리 과정이 어떻게 진행되는지 살펴보자.

  • 시퀀스 다이어그램 참고)
    • 참고) user1과 user2가 있다고 가정하자. 둘다 동일한 계정으로 로그인에 시도한다.
    • user1이 인증을 시도한다. 그러면 인증 처리 필터인 UsernamePasswordAuthenticationFilter 가 인증 처리를 진행한다. 이때 해당 필터는 SessionManagementFilter 필터가 가지고 있는 각각의 클래스들을 호출하면서 세션 관련된 기능들을 처리한다.
      • 1) UsernamePasswordAuthenticationFilter 는 가장 먼저 동시적 세션 제어를 처리하는 클래스인 ConcurrentSessionControlAuthenticationStrategy 를 호출한다. 해당 클래스는 인증 계정으로 생성된 세션이 몇개인지를 확인하고, 최대 허용 세션 개수를 넘어서는지 확인한다. 참고로 현재는 user1이 처음으로 접속하므로 session count가 0이다. 따라서 해당 클래스는 정상적으로 문제없이 통과한다. 2) 그리고 ChangeSessionIdAuthenticationStrategy 클래스를 호출한다. ChangeSessionIdAuthenticationStrategy 는 세션 고정 보호 처리를 하는 클래스이다. 따라서 새롭게 세션쿠키를 발급한다. 3) 그리고 RegisterSessionAuthenticationStrategy 클래스를 호출한다. 이 클래스는 사용자의 세션을 등록, 저장하는 역할을 한다.
    • 이후 user2가 동일 계정으로 인증을 시도한다.
      • 1) 동일하게 ConcurrentSessionControlAuthenticationStrategy 가 호출된다. 그런데 해당 인증 계정은 이전 user1과 동일한 계정이다. 따라서 이미 그 계정으로 생성된 세션이 1개 있으므로, 이제 최대 허용 개수를 넘게된다.
        • 여기서, 동시 세션 제어 전략으로 인증 실패 전략을 사용한 경우, SessionAuthenticationException 인증 예외가 발생하여 세션이 생성되지 못하고, 인증에 실패한다. ( 이후 2), 3) 은 호출도 하지 않고, 인증 실패로 끝난다. )
        • 세션 만료 전략을 사용한 경우라면, session.expireNow() 를 통해 user1의 세션을 만료시키는 전략을 사용한다. 그리고 이후 2), 3) 절차를 통해 인증에 성공한다.
        • 참고) ConcurrentSessionControlAuthenticationStrategy > allowableSessionsExceeded(..)
          • if 문: 세션 만료 전략을 사용한 경우.
          • else 문: 인증 실패 전략을 사용한 경우.
          • exceptionIfMaximumExceeded: maxSessionsPreventsLogin 값을 의미한다.
    • 현재 서버는 user1 과 user2의 세션이 생성된 상태이다. (동일 계정으로 생성된 세션이 두개이다.)
    • 이 상태에서 user1이 인증이 필요한 특정 자원에 접근한다. 그리고 이때, 매 요청마다 호출되는 ConcurrentSessionFilter가 동작하고, user1의 세션 만료 여부를 체크한다. 해당 필터는 session.isExpired() 를 통해 user1의 만료 여부를 체크한다. 그 값이 true인 경우, 즉시 그 사용자의 세션을 만료시키도록 로그아웃 처리를 진행하고, 오류 페이지를 응답한다.
    • (정리) 사용자가 인증할 때, 인증 필터는 SessionManagementFilter 필터가 가지고 있는 각각의 클래스들을 활용해서 세션 고정 보호, 동시 세션 제어, 세션 등록 등을 처리한다. 그리고 ConcurrentSessionFilter는 매 요청마다 사용자의 세션 만료 여부를 확인하여, 세션을 만료시켜야 한다면, 로그아웃 시키고, 오류페이지를 응답한다.

 

✔️ 참고


강의를 듣고 정리한 글입니다. 코드와 그림 등의 출처는 정수원 강사님께 있습니다.

profile
현실에서 한 발자국

0개의 댓글