동시 세션 제어
동시 세션 제어는 동일한 계정으로 인증을 받을 때 즉, 로그인을 했을 때 생성되는 세션에 대해서 최대 세션 허용 개수를 초과했을 때 어떻게 그 세션 개수를 초과하지 않고 유지할 수 있는지에 대한 것이다.
예를 들어 서버에서 설정한 동일한 계정에 대한 세션 최대 개수가 1개라고 하면, 웹에서 로그인을 하면 세션이 1개가 생성된다. 그리고 모바일에서도 똑같은 계정으로 로그인했을 때는 세션이 2개가 된다. 이 상황에 대해서 허용 세션은 1개인데 나머지 1개를 어떻게 처리할지에 대해서 처리하는 것을 동시 세션 제어를 통해 설정할 수 있습니다.
스프링 시큐리티는 밑의 그림과 같이 두 가지 전략으로 동시 세션 제어를 제공하고 있습니다.
동일 한계정으로 허용되는 세션 개수는 1개로 가정합니다.
1. 이전 사용자 세션을 만료시키는 전략
동일한 계정으로 사용자 1은 회사, 사용자 2는 집에서 로그인함.
사용자 1이 회사에서 로그인해서 세션이 생선 된다.
서버에는 사용자 1로 세션이 하나 있고 동일 한계정으로 사용자 2가 집에서 로그인합니다.
그러면 사용자 2의 세션이 생성됩니다.
서버에는 동일 한계정으로 세션이 2개가 생성됩니다.
서버에서 최대 세션 개수가 1개이므로 지금은 초과된 상태입니다.
두 번째 사용자가 동일 한계정으로 로그인하면 첫 번째 세션을 만료시키는 것입니다.
그렇게 되면 사용자 1의 세션은 만료되고 사용자 2는 사용할 수 있다.
이렇게 되면 회사에 로그인해놓고 온 제 계정이 저절로 로그아웃 처리가 되면서 제 계정에 대한 걱정을 안 해도 됩니다.
그래서 세션 1개를 유지할 수 있는 전략입니다.
2. 현재 사용자 인증 실패하는 전략
사용자 1이 로그인합니다.
사용자 1 세션이 생성됩니다.
동일 한계정으로 사용자 2가 로그인합니다.
서버가 사용자2가 로그인할 때 서버에 사용자 1 세션이 있으니깐 사용자 2의 인증 예외를 발생시켜 서버에는 사용자 1의 세션만 유지되는 것입니다.
세션 관리 기능 적용
http.sessionManagement() 이렇게하면 세션관리 기능이 작동합니다.
.maximumSessions(1) // 최대 허용 가능 세션 수 , -1 : 무제한 로그인 세션 허용
.maxSessionsPreventsLogin(true) // 동시 로그인 차단함, false : 기존 세션 만료(default) 1번전략
.invalidSessionUrl("/invalid") // 세션이 유효하지 않을 때 이동 할 페이지
.expiredUrl("/expired ") // 세션이 만료된 경우 이동 할 페이지
두가지를 설전 다했을때 invalidSessionUrl 우선순위이다.
세션 고정 보호
사용자, 공격자, 웹 애플리케이션이 있다.
공격자가 서버에 접속하면 세션 아이디를 준다.
사용자한테 공격자의 세션 아이디를 심어놓는다.
사용자는 공격자의 세션 쿠키로 로그인 시도를 한다.
사용자가 인증을 받을 때 공격자의 JSESSIONID로 인증을 받은 상태이기 때문에 사용자와 공격자가 똑같은 세션을 공유하게 됩니다. 공격자는 인증을 하지 않고도 사용자의 정보를 공유받을 수 있습니다.
이런 공격을 보호하기 위해 스프링 시큐리티가 세션 고정 보호라는 걸 제공하게 됩니다.
그래서 인증을 성공할 때마다 새로운 세션과 새로운 쿠키가 생성되게 됩니다. 이게 세션 고정 보호입니다.
http.sessionManagement()
.sessionFixation().changeSessionId() // 기본값
. sessionFixation(). changeSessionId() // 기본값입니다. 안 적어도 기본적으로 지원을 해줌.
세션 정책
http.sessionManagement() : 세션 관리 기능이 작동함
http.sessionManagement(). sessionCreationPolicy(SessionCreationPolicy. If_Required)
sessionCreationPolicy()에 4개의 값을 설정할 수 있음.
- SessionCreationPolicy. Always : 스프링 시큐리티가 항상 세션 생성, 조건에 상관없이 세션을 항상 생성
- SessionCreationPolicy. If_Required : 스프링 시큐리티가 필요시 생성(기본값)
- SessionCreationPolicy. Never : 스프링 시큐리티가 생성하지 않지만 이미 존재하면 사용
- SessionCreationPolicy. Stateless : 스프링 시큐리티가 생성하지 않고 존재해도 사용하지 않음==JWT 할 때 사용
세션 제어 필터
세션 제어하는 필터에는 두 개가 있는데 이전 시간에 배운 SessionManagementFilter와 ConcurrentSessionFilter가 있습니다. 이 두 개의 필터는 동시적 세션 제어를 하기 위해 연계되는 필터입니다. 지금은 ConcurrentSessionFilter에 대해서 알아보겠습니다.
SessionManagementFilter
1. 세션 관리
• 인증 시 사용자의 세션정보를 등록, 조회, 삭제 등의 세션 이력을 관리
2. 동시적 세션 제어
• 동일 계정으로 접속이 허용되는 최대 세션수를 제한
3. 세션 고정 보호
• 인증할 때마다 세션 쿠키를 새로 발급하여 공격자의 쿠키 조작을 방지
4. 세션 생성 정책
• Always, If_Required, Never, Stateless
ConcurrentSessionFilter
• 매 요청마다 현재 사용자의 세션 만료 여부 체크를 합니다.
• 세션이 만료로 설정되었을 경우 즉시 만료 처리를 합니다.
• session.isExpired() == true (세션이 만료로 설정이 true라면)
• 로그아웃 처리
• 즉시 오류 페이지 응답
“ This session has been expired ”
SessionManagementFilter와 ConcurrentSessionFilter는 동시적 세션 제어하기 위해 서로 연계해 처리하고 있다.
동시적 세션 제어 흐름
그러면 세션이 두 개가 생성이 된다. 최대 세션 허용 개수가 1개로 설정되어있다면 세션 허용개수가 초과되어
이전 사용자 세션 만료 전략으로 만료를 시킵니다.==session.expireNow()
이때 이전 사용자가 서버에 접속하면
session.isExpired()으로 이미 세션이 만료된 상태이다.
ConcurrentSessionFilter가 매 요청마다 사용자 세션 여부 만료를 처리하기 때문에 이전 사용자가 세션이 만료되었는지 안되었는지 확인을 합니다. 이 확인은 SessionManagementFilter에서 세션을 참조해서 확인을 합니다.
session.expireNow() 참조해서 만료되도록 설정되어있으니깐 로그아웃하고 오류 페이지를 응답합니다.
'Spring Boot > Spring Security' 카테고리의 다른 글
[Spring Security] 예외 처리 및 요청 캐시 필터 (0) | 2022.06.29 |
---|---|
[Spring Security] 권한 설정 (0) | 2022.06.29 |
[Spring Security] Remember Me 인증, RememberMeAuthenticationFilter (0) | 2022.06.29 |
[Spring Security] Logout처리, LogoutFilter (0) | 2022.06.29 |
[Spring Security] Form Login 인증 필터 (0) | 2022.06.29 |
댓글