인프런에서 진행하는 정수원 강사님의 "스프링 시큐리티 - Spring Boot 기반으로 개발하는 Spring Security" 강의를 보고 학습을 위해 개인적으로 추가/정리한 글임을 알립니다.
[ 동시 세션 제어, 세션 고정 보호, 세션 정책 ]
> 동시 세션 제어
동일한 계정으로 인증을 받을 때 생성되는 세션에 허용 개수가 초과 되었을 경우 어떻게 세션을 유지하는 지에 대한 제어를 말한다.
Spring-Security에서는 두 가지 전략으로 동시세션제어를 하게 된다.
default 최대 세션 허용 개수 : 1개
동일한 계정으로 들어온 사용자에 대해서 세션 허용 개수
- 이전 사용자 세션 만료
- 사용자 1의 세션은 만료 되고 사용자 2의 세션은 사용가능 하다.
- 현재 사용자 인증 실패
- 뒤늦게 들어온 사용자 2의 세션을 차단해서 사용자 1의 세션은 사용가능 하다.
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement()
.maximumSession(1) // 최대 허옹 가능 세션 수(default 1)
.maxSessionsPreventsLogin(true) // 동시 로그인 차단한다 -> true:현재사용자인증실패 // (default)false:기존세션만료
.invalidSessionUrl("/invalid") // 세션이 유효하지 않을 때 이동 할 페이지
.expiredUrl("/expired") // 세션이 만료된 경우 이동 할 페이지
;
}
이 때 invalidSessionUrl()
과 expiredUrl()
을 모두 설정했을 땐 invalidSessionUrl()
이 우선적용 된다.
false(기존 사용자 세션 만료)로 설정하면 사용자 1과 사용자 2 모두 세션이 실행이 되긴한다.
그러나 현재 사용자의 세션이 만료되었는지 안되었는지 ConcurrentSessionFilter
가 체크를 해서 이전 사용자의 세션을 만료시키게 된다.
This session has been expired (possibly due to multiple concurrent logins being attempted as the same user).
> 세션 고정 보호
공격자가 임의로 JSESSIONID
를 웹에 심어놓고 사용자도 공격자의 세션 쿠키를 사용하게 되면,
사용자와 공격자 모두 동일한 세션을 공유하게 되는 참사가 발생한다.
이런걸 세션 고정 공격이라고 한다.
그래서 Spring-Security는 세션 고정 보호를 제공한다.
사용자가 비록 공격자가 심어놓은 쿠키로 접속을 해서 인증을 시도한다 하더라도, 인증할 때 마다 새로운 세션을 생성하면 새로운 쿠키가 만들어질 거고 공격자가 심어놓은 JSESSIONID
는 달라지기 때문에 사용자의 정보를 공유할 수 없다.
즉, 인증에 성공할 때마다 새로운 세션을 생성되고 새로운 JSESSIONID
를 발급하도록 하는 것이 세션 고정 보호이다.
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement()
.sessionFixation().changeSessionid() // 기본값, (none, migrateSession, newSession)
;
}
여기서 changeSessionid()
는 서블릿 3.1 이상에서의 기본값이고 그 이하 버전에서의 기본값은 migrateSession()
이다.
changeSessionid과 migrateSession 이 두 개의 옵션은 이전 세션의 설정한 여러 속성값들을 그대로 사용할 수 있도록 지원하며
newSession은 이전 세션에서 설정한 여러 속성값들을 사용하지 못하고 새롭게 속성값들을 설정해야 한다는 특징이 있다.
none 옵션은 새롭게 세션을 생성하지 않고, 공격에 취약하다.
> 세션 정책
세션 관리 기능이 작동하는 정책
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.If_Required)
;
}
SessionCreationPolicy.Always
: 스프링 시큐리티가 항상 세션을 생성한다.SessionCreationPolicy.If_Required
: 스프링 시큐리티가 필요 시에 생성한다.(기본 값)SessionCreationPolicy.Never
: 스프링 시큐리티가 생성하지 않지만 이미 존재하면 사용한다.SessionCreationPolicy.Stateless
: 스프링 시큐리티가 생성하지 않고 존재해도 사용하지 않는다.JWT
이라는 웹 토큰을 이용해 토큰에 사용자의 정보나 추가적인 사항들을 저장하고 인증을 하는 방식이다.- 이 때 는 Stateless 옵션을 사용한다.
< SessionManagementFilter, ConcurrentSessionFilter >
추가로 세션 관리에 사용되는 필터들에 대해서 알아보겠다!
SessionManagementFilter
- 세션 관리
- 인증 시 사용자의 세션정보를 등록, 조회, 삭제 등의 세션 이력을 관리
- 동시적 세션 제어
- 동일 계정으로 접속이 허용 되는 최대 세션 수를 제한
- 세션 고정 보호
- 인증할 때마다 세션쿠키를 새로 발급해서 공격장의 쿠키 조작을 방지
- 세션 생성 정책
- Always, If_Required, Never, Stateless
- 세션 관리
ConcurrentSessionFilter
- 매 요청마다 현재 사용자의 세션 만료 여부를 체크해서
- 세션이 만료되었을 경우에는 즉시 만료 처리를 한다.
session.isExpired() == true
- 로그아웃 처리
- 즉시 오류 페이지 응답
- 이 필터는 동시적 세션제어를 하기 위해 SessionManagementFilter와 항상 연계되어 있다.
사용자1과 2의 로그인 과정에서 동시적 세션 접근제어를 하는 과정
- 사용자1이
UsernamePassworddAuthenticationFilter
는 가장 먼저ConcurrentSessionControlAuthenticationStrategy
클래스를 가장 먼저 호출한다. 이 계정으로 생성된 세션의 개수가 얼마인지 확인한다. 이 때는 session count가 0이므로 문제없이 통과한다. - 그 이후
ChangeSessionIdAuthenticationStrategy
클래스를 호출해서 세션 고정 보호를 처리한다. 새롭게 세션을 생성하고 새로운 세션 쿠키를 발급한다. - 세 번째로
RegisterSessionAuthenticationStrategy
클래스를 호출해서 사용자의 세션을 등록하고 저장하는 역할을 한다. 이 때 session count가 1이 된다. - 이 상태에서 사용자2가 사용자1가 동일한 계정으로 인증을 시도한다.
- 해당 계정으로 생성된 세션이 한개가 있고, 최대 허용 세션 개수도 1로 똑같으므로 두 가지 전략을 타게 된다.
- 인증 실패 전략일 경우
SessionAuthenticationException
이 발생하고 인증이 실패가 된다.- 더이상 다른 클래스를 호출하지 않고 인증이 끝나버린다!
- 이전 사용자의 세션만료 전략일 경우
- 사용자 1의 세션을 만료 시킨다 :
session.expireNow()
- 사용자 2의 세션을 인증한다 : 똑같이 1,2,3의 과정을 거친다.
- 이 때 사용자 1이 다시금 자원에 접근을 하게 되면 ConcurrentSessionFilter가 사용자의 세션 만료여부를 체크한다 :
session.isExpired() == true
- 사용자 1의 세션을 만료 시킨다 :
- 인증 실패 전략일 경우
'웹 프로그래밍 > [ Spring Security ]' 카테고리의 다른 글
[ Spring Security ] 05. 인증/인가 API의 예외처리 (0) | 2021.12.12 |
---|---|
[ Spring Security ] 04. 인가 API와 표현식 (0) | 2021.12.09 |
[ Spring Security ] 02. 익명 사용자 인증처리 필터 : AnonymousAuthenticationFilter (0) | 2021.12.08 |
[ Spring Security ] 01. Remember-Me 인증이란? (0) | 2021.12.07 |
[ Spring Security ] 00. LoginForm 인증 API 및 Filter의 이해 (0) | 2021.12.06 |