안녕하세요. 이번 포스팅은 Spring Security의 Remember_me 기능을 정리하는 글입니다.
JSESSIONID가 만료되거나 없더라도, 쿠키를 통해 어플리케이션이 사용자를 기억하는 기능입니다. Remember-Me는 토큰 쿠키를 이용하여, 유효성을 검사하고 로그인 처리를 진행합니다.
http.
.rememberMe()
.rememberMeParameter("remember")
.tokenValiditySeconds(3600)
.userDetailsService(userDetailsService);
- rememberMe(): rememberMe 기능을 적용
- rememberMeParameter(): 폼의 check-box명
- alwaysRemember(): 체크박스 설정 유무와 상관없이 항상 실행 (default: false)
- userDetailsService(): 사용자 정보
- Request 요청이 들어오면 RememberMeAuthenticationFilter가 작동합니다
- RememberMeService 인터페이스는 토큰기반의 Service 구현체와 영속적인 토큰 기반의 Service 구현체가 존재합니다. 해당 필터는 config에 설정된 구현로직에 따라 해당 구현체를 연결합니다.
- TokenCookie를 추출하여 토큰에 대한 유효성을 판단합니다.
- 토큰이 발급자의 토큰과 일치하는지, 맞다면 유저의 계정이 존재하는지 파악하여 정상 처리되면 새로운 Authentication 객체를 생성하여 SecurityContext에 값을 전달합니다.
- 새로운 Authentication 객체가 생성되었으므로 Session값이 새롭게 설정됩니다.
어플리케이션의 Session이 종료되거나 없더라도 remember_me 쿠키가 남아있다면, 유효성 검사를 통해 자동 로그인 방식을 유지할 수 있습니다. 기존에 있던 JSESSIONID를 삭제하고 어플리케이션을 다시 실행하면, 혹은 재요청을 보내면 로그인 절차를 거치지 않고 새로운 SessionID가 생성되며 로그인이 유지되는 것을 확인할 수 있습니다.
'remember_me 기능은 세션 고정 보호 정책과 트레이드 오프가 발생하지 않는가?'에 대한 궁금증이 생겼습니다. 즉, 새 remember_me는 로그인을 유지할 수 있는 쿠키를 발행하여 세션을 생성하는 것이고, 세션 고정 보호는 인증할 때마다 세션쿠키를 발급하여 공격자의 쿠키 조작을 방지하는 것입니다. 따라서, remember_me를 설정하면 세션이 고정되는 것이 아닌가? 라는 궁금증이 생겼습니다.
아래의 그림은 세션이 유지되면 공격자에게 보안에 취약한 상황에 처할 수 있는 것을 보여주는 다이어그램입니다. 만약 remember_me에서 세션이 동일하게 유지된다면 공격자에게 무방비 노출될 수 있습니다.
이에 대해 제가 이해한 바는 다음과 같습니다. 위에서 정리했듯, remember_me를 설정하더라도 Authentication 객체가 생성되고 SecurityContext에 값이 담기고 세션이 생성되면, 항상 다른 세션이 생성됩니다. 즉, SessionManagementFilter가 세션 고정 보호를 처리하며 다른 세션을 생성하기 때문입니다.
따라서, remember_me를 설정하더라도 두 관계는 트레이드오프가 발생하는 것이 아니라 SessionManageMentFilter가 remember_me가 더 안전하게 구성될 수 있도록 세션ID를 계속 바꿔주는 기능을 수행한다고 할 수 있습니다.
잘못된 점이 있다면, 댓글 부탁드립니다!
감사합니다!
참고 자료: 정수원님 - 스프링 시큐리티 - Spring Boot 기반으로 개발하는 Spring Security