스프링 시큐리티 - Remember Me 기능

SeungTaek·2022년 2월 11일
2
post-thumbnail

본 게시물은 스스로의 공부를 위한 글입니다.
잘못된 내용이 있으면 댓글로 알려주세요!

Remember Me 인증

JSESSIONID이 만료되거나 쿠키가 없을 지라도 어플리케이션이 사용자를 기억하는 기능이다. 자동 로그인 기능을 떠올리면 쉽다.
Remember-Me 토큰 쿠키를 이용한다. 서버는 이 토큰의 유효성을 검사하고, 검증되면 사용자는 로그인된다.


설정 코드를 보자.

@Autowired
UserDetailsService userDetailsService;
    ...생략...
    
http.rememberMe() // rememberMe 기능 작동함
  .rememberMeParameter("remember") // default: remember-me, checkbox 등의 이름과 맞춰야함
  .tokenValiditySeconds(3600) // 쿠키의 만료시간 설정(초), default: 14일
  .alwaysRemember(false) // 사용자가 체크박스를 활성화하지 않아도 항상 실행, default: false
  .userDetailsService(userDetailsService); // 기능을 사용할 때 사용자 정보가 필요함. 반드시 이 설정 필요함.
  1. .rememberMeParameter() 사용자가 로그인 페이지를 만들때 여기를 주의해야 한다. 보통 checkbox로 만들텐데, 이때 name을 여기서 설정한 값과 동일하게 해줘야 한다.
  2. tokenValiditySeconds 초 단위로 remember-me 토큰의 유효시간을 설정할 수 있다.
  3. .alwaysRemember 사용자가 이 기능을 사용한다고 체크하지 않아도 자동으로 사용하게 하는 기능이다.
  4. userDetailsService 이 기능을 사용하려면 사용자 정보가 필요하다. 따라서 객체를 주입받은 후 넣어주자.

remember-me 쿠키 사이클

  1. 로그인(인증) 성공 = remember-me 쿠키 발급
  2. 로그인(인증) 실패 = remember-me 쿠키가 있다면 무효화
    • 즉, 로그인이 성공했어도 사용자가 임의로 로그인 페이지로 돌아간 후 인증에 실패하면, 있는 쿠키도 무효화 시킨다.
  3. 로그아웃 = remember-me 쿠키가 있다면 무효화
  4. 만료시간 = 지날 겨웅 무효화

실습해보기

Remember Me를 체크하지 않고 로그인 해보자.
로그인 쿠키로 JSESSIONID가 들어온다. 세션 쿠키 방식으로, 로그인을 인증할 때 사용된다. 하지만 세션이 만료되거나 웹 브라우저를 닫거나 등으로 쿠키가 없어진다면? 다시 로그인 해야한다.
크롬의 개발자도구를 이용해 JSESSIONID을 지우고 새로고침하면 다시 로그인하는 창이 뜨는것을 확인할 수 있다.


Remember Me를 체크 후 로그인 해보자.
JSESSIONID 말고도 remember-me 라는 쿠키가 날라왔다.

이 쿠키에는 회원 아이디와 비밀번호 등이 인코딩 되어 들어있다. 따라서 JSESSIONID이 다른 요인에 의해 삭제되거나 request header에 보내지 않더라도 서버에서는 회원 인증을 하고, 실제 회원과 일치한 정보가 있다면 로그인을 해주고 거기에 JSESSIONID 쿠키까지 새로 만들어서 보내준다.
크롬의 개발자도구를 이용해 JSESSIONID을 지우고 새로고침해도 자동 로그인이 되어있다. 뿐만 아니라 JSESSIONID도 새롭게 발급해준다.


RememberMe 로직

1. 실행 조건

RememberMeAuthenticationFilter 필터가 실행될 조건은 다음과 같다.

  1. 스프링 시큐리티에서 사용하는 인증객체(Authentication)가 Security Context에 없어야 함
    • 세션 만료(time out), 브라우저 종료, 세션id 자체를 모르는 등의 요인이 있다. 인증객체가 있다라는 소리는 로그인이 정상적으로 되었고, 회원 정보도 정상적으로 세션에서 찾을 수 있다라는 이야기이다. 따라서 이 필터가 실행될 필요가 없다.
  2. 사용자 request header에 remember-me 쿠키 토큰이 존재해야 한다.

2. 구현체의 차이

위의 실행 조건이 부합하다면 RememberMeService(인터페이스)가 실행된다. 실제 구현체 2가지 있는데, 그 차이는 다음과 같다.

  1. TokenBasedRememberMeServices: 서버 메모리에 있는 쿠키와 사용자가 보내온 remember-me 쿠키를 비교(기본적으로 14일간 존재)
  2. PersistentTokenBasedRememberMeServices: DB에 저장되어 있는 쿠키와 사용자가 보내온 remember-me 쿠키를 비교(이름 그대로 persistent)

3. 로직

  1. Token Cookie이 존재하면 추출
  2. Decode Token하여 토큰이 정상인지 판단
  3. 사용자가 들고온 토큰과 서버에 저장된 토큰이 서로 일치하는지 판단
  4. 토큰에 저장된 정보를 이용해 DB에 해당 User 계정이 존재하는지 판단
  5. 위 조건을 모두 통과하면 새로운 인증객체(Authentication)을 생성 후 AuthenticationManager에게 인증 처리를 넘긴다. (물론 Security Context에도 인증 객체를 저장한다.)
  6. 이후 response 될 때 JSESSIONID를 다시 보내준다.

remember-me 토큰 초기화 시점

rembmer-me 토큰은 새롭게 로그인 인증을 받는 경우 초기화 된다.
그럼 JSESSIONID이 만료해서 remember-me 토큰으로 로그인 해도 초기화 되는거 아닌가?
여기서 주의해야할 것은 새롭게라는 단어다. 즉, remember-me 쿠키로 인증을 진행해서 로그인 될 경우에는 JSESSIONID은 초기화되지만, remember-me 토큰은 초기화가 안된다. 두 토큰은 별개이다.



Reference

인프런 '스프링 시큐리티 - Spring Boot 기반으로 개발하는 Spring Security' (정수원)

profile
I Think So!

0개의 댓글