Spring Security - UserDetailsService with Remember-me feature (TokenBasedRememberMeServices)
여러가지 서비스를 이용하다보면, 자동 로그인하기라는 체크 박스를 기본적으로 확인할 수 있다.
UserDetailsManager 는 UserDetailsService interface 를 상속받는다.
아래는 UserDetailsManager 를 구현한 커스텀 UserDetailsService 이다.
createUser(UserDetails user) 메서드는 스프링 시큐리티가 해당 UserDetails 를 관리할 수 있도록, SecurityContextHolder 에 setAuthentication() 메서드를 통해서 추가해준다.
나머지 아래에 updateUser(), deleteUser(), changePassword(), userExists() 는 편의상 아직 구현하지 않았다.

아래의 TokenBasedRememberMeServices 의 ProcessAutoLoginCookie() 메서드의 중간쯤에 getUserDetailsService().loadUserByUsername() 메서드를 호출하고 있는것을 확인할 수 있다.
스프링 시큐리티는 사용자명과 만료일을 추출한 후, 사용자명을 사용해 UserDetailsService (UserDetailsService 를 사용하지 않는다면, Remember-Me 기능을 사용할 수 없다는 단점이 있다.) 에서 사용자 패스워드를 검색한다. 여기서 key 는 rememberMe 메서드를 사용해 제공했기 때문에 위에서 설정한 값을 알고 있다.
토큰 기반 Remember-Me 기능은 TokenBasedRememberMeServices 의 processAutoLoginCookies() 메서드를 사용한다. 해당 메서드안에서 UserDetailsService 의 loadUserByUsername() 메서드 호출을 통해 UserDetails 를 가져와 시그니쳐를 계산한다.
물론, AbstractRememberMeServices 를 상속받아 커스텀 RememberMeServices 를 재정의하고, 스프링 시큐리티에 커스텀 RememberMeServices 를 사용하도록 할 수 있을 것 같아 보인다. ( 시간 날 때 해보고 공유할 수 있도록 해보겠다. 해보지 않아서 확신하기 어렵다.)
그 결과 JSESSIONID 라는 세션 정보를 담은 쿠키만 존재한다.
remember-me 쿠키 이름을 다르게 설정하고 싶다면, rememberMeCookieName() 메서드를 통해서 설정이 가능하다.
SSL 및 기타 네트워크 보안 기술을 함께 사용한다면 해당 유형의 공격을 방어할 수 있다.
하지만, 저장된 사용자의 세션을 도용하거나 손상시키는 XSS 와 같은 공격 기법도 있다. 따라서 Remember-Me 기능은 사용자에게는 편리한 기능이지만, 보안 위험이 도사리고 있으므로 주의해야 한다.
다음은, 영구 토큰 기반 Remember-Me 에 대해 알아보자.
//next
스프링 시큐리티에서 지원하는 Remember-me 라는 기능이 바로 그 기능이다.
웹사이트를 자주 방문하는 사용자에게 편리한 기능이다. 사용자가 웹 브라우저를 종료한 후에도 사용자의 웹 브라우저에 Remember-Me 쿠키를 저장함으로써 재방문 시 사용자를 기억하는 기능이다. 이는 사용자가 사용자명이나 패스워드를 다시 입력할 필요가 없다.
스프링 시큐리티 Remember-Me 기능에는 두 가지가 있다.
- 토큰 기반의 Remember-Me 기능으로, 암호화 시그니처에 의존한다. (TokenBasedRememberMeServices)
- 영구 토큰 (Persistent Token) 기반 Remember-Me 기능이며, 데이터베이스 (datastore) 가 필요하다. (PersistentTokenBasedRememberMeServices)
먼저, 토큰 기반 Remember-Me 기능을 살펴보자.
아래의 로그인 화면과 같이, login.html 에서 Remember me 체크 박스를 만들어준다.
그리고 name attribute 설정을 해준다.
spring security remember-me 기능의 default parameter 는 "remember-me" 이다.
물론 다르게 설정이 가능하다.
아래는 시큐리티 설정이다.
HttpSecurity 에 rememberMe() 와 key() tokenValiditySeconds() 메서드를 통해 설정한다.
key() -> Remember-Me 쿠키의 시그니처 생성 시 사용되는 고유한 키를 정의한다. 애플리케이션의 고유 이름을 포함한 최소 36자 길이의 문자열을 사용할 것을 추천한다.
tokenValiditySeconds -> Remember-Me 쿠키의 만료 시간을 설정한다. -1 로 설정한다면, 2주를 의미한다.
토큰 기반 Remember-Me 기능의 동작 원리
Remember-Me 기능은 Base64 인코딩 문자열을 포함하는 쿠키를 사용자 웹 브라우저에 설정한다.
- 사용자명
- 만료 날짜 및 시간
- 만료 날짜 및 시간, username, password 및 rememberMe 메서드의 key 애트리뷰트에 대한 MD5 해시 값 (시그니쳐)
UserDetailsManager 는 UserDetailsService interface 를 상속받는다.
아래는 UserDetailsManager 를 구현한 커스텀 UserDetailsService 이다.
createUser(UserDetails user) 메서드는 스프링 시큐리티가 해당 UserDetails 를 관리할 수 있도록, SecurityContextHolder 에 setAuthentication() 메서드를 통해서 추가해준다.
나머지 아래에 updateUser(), deleteUser(), changePassword(), userExists() 는 편의상 아직 구현하지 않았다.

아래의 TokenBasedRememberMeServices 의 ProcessAutoLoginCookie() 메서드의 중간쯤에 getUserDetailsService().loadUserByUsername() 메서드를 호출하고 있는것을 확인할 수 있다.
스프링 시큐리티는 사용자명과 만료일을 추출한 후, 사용자명을 사용해 UserDetailsService (UserDetailsService 를 사용하지 않는다면, Remember-Me 기능을 사용할 수 없다는 단점이 있다.) 에서 사용자 패스워드를 검색한다. 여기서 key 는 rememberMe 메서드를 사용해 제공했기 때문에 위에서 설정한 값을 알고 있다.
토큰 기반 Remember-Me 기능은 TokenBasedRememberMeServices 의 processAutoLoginCookies() 메서드를 사용한다. 해당 메서드안에서 UserDetailsService 의 loadUserByUsername() 메서드 호출을 통해 UserDetails 를 가져와 시그니쳐를 계산한다.
물론, AbstractRememberMeServices 를 상속받아 커스텀 RememberMeServices 를 재정의하고, 스프링 시큐리티에 커스텀 RememberMeServices 를 사용하도록 할 수 있을 것 같아 보인다. ( 시간 날 때 해보고 공유할 수 있도록 해보겠다. 해보지 않아서 확신하기 어렵다.)
이제 스프링 시큐리티는 사용자명, 만료일, 패스워드 및 key 를 사용해 예상되는 시그니처를 계산한다. 그 후, 예상되는 시그니쳐와 쿠키의 시그니쳐를 비교한다.
예상되는 시그니쳐와 쿠키의 시그니쳐가 일치한다면, 사용자명과 만료일이 유효하다는 것을 신뢰할 수 있다. 따라서 개념적으로 Remember-Me Key(애플리케이션만 알고 있는) 와 사용자 패스워드(사용자만이 알고 있는) 를 모른 채 시그니쳐를 위조하는 것은 불가능하다. 즉, 시그니처가 일치하고 토큰이 만료되지 않은 경우 합법적인 사용자만이 로그인할 수 있다.
아래는 Remember me 체크박스를 체크하지 않고 로그인을 한다.
이번에는 Remember me 체크 박스를 체크하고 로그인한다.
아래와 같이 remember-me 라는 쿠키가 추가적으로 생겼다.
Remember-Me 의 안전성
사용자의 편의를 위해 제공하는 모든 기능은 안전한 사이트를 보안 위험에 노출시킬 위험성을 항상 안고 있다. Remember-Me 기능도 기본 형태로 사용하면 악의적인 사용자가 중간에서 사용자의 쿠키를 가로채서 재사용할 위험이 있다.
하지만, 저장된 사용자의 세션을 도용하거나 손상시키는 XSS 와 같은 공격 기법도 있다. 따라서 Remember-Me 기능은 사용자에게는 편리한 기능이지만, 보안 위험이 도사리고 있으므로 주의해야 한다.
다음은, 영구 토큰 기반 Remember-Me 에 대해 알아보자.
//next
댓글
댓글 쓰기