한울이

[SPRING] ConcurrentSessionControlAuthenticationStrategy session expire 실패 본문

PROGRAMMING

[SPRING] ConcurrentSessionControlAuthenticationStrategy session expire 실패

gksdnf050 2023. 3. 26. 15:50

1. 문제상황

  • 조건
    • 똑같은 계정으로 로그인 시도 하는 부하테스트
    • spring security maximum session 10으로 설정

부하 테스트 도중 session을 expire 시킬 수 없다는 log 가 찍힘

2. debugging

spring security 는 ConcurrentSessionControlAuthenticationStrategy 에서 동일한 유저의 maximunm session 을 처리함

session registry를 통해 모든 session을 가져온 후 maximum session count 확인

(SpringSessionBackedSessionRegistry 사용중)

만약 설정한 maximum session count 를 초과하면 가장 오래된 session을 만료시킴

(spring security에서 초과된 session 을 만료시킬 때 삭제 하는게 아니고 session attribute 에

expire attribute를 추가함)

이 부분에서 session 을 가져와서 expire 시키려 할때 session 이 null인 상황 (SpringSessionBackedSessionInformation 사용중)

  • 첫번째 의심

동일한 계정 로그인으로 부하테스트 중이므로 동시에 로그인 시도 요청이 왔을 거고

위에서 SpringSessionBackedSessionRegistry 를 통해 가져온 세션 list 를 동시에 여러명이

expire 하려고 하니 이미 expire 되어서 이러한 상황이 발생 할 것이라고 생각

(RedisIndexedSessionRepository 사용중)

loaded.isExpired() 이 부분에서 session 이 이미 expire되어서 null 을 리턴하므로 발생 했을 것이라고 생각

 

하지만

 

loaded.isExpired()는 session 값을 가져와서 expire attribute를 확인 하는 것이 아닌

session을 가져와서 시간을 비교해서 expired가 되었는지 확인

즉, 위에서 null 을 return 했다는 것은 애초에 session이 없다는 것

즉, 어디선가 session을 삭제 했다는 것 (expire 를 시킨 것이 아님 - expire attribute를 넣은 것이 아님)

  • 확인

원인을 계속 찾아보던 중

만약 이미 로그인 되어있던 session cookie 를 가지고 또 로그인을 시도하면

이전 session cookie 값을 삭제 시킨다는 것을 알게됨

 

maximum session 에 도달 했을 때

SessionFixationProtectionStrategy 으로 인해

요청한 session 값을 삭제하고 새로운 session 값을 발행

부하테스트를 할때 header에 cookie 값을 넣지 않고 로그인 요청을 보냈는데

(즉 이전 session cookie 값이 없으므로 이전 session cookie 값을 삭제 하지 않을 거라고 생각했음)

자동적으로 response 로 받은 cookie 값을 포함해서 요청을 보내고 있었다.

 

그러므로 동시에 여러 요청이 들어왔을 때 이미 삭제된 session 을 다른 스레드에서 또 삭제하려고 하니

이러한 log 가 찍힌 것이었다.

Comments