인프런에서 진행하는 정수원 강사님의 "스프링 시큐리티 - Spring Boot 기반으로 개발하는 Spring Security" 강의를 보고 학습을 위해 개인적으로 추가/정리한 글임을 알립니다.
[ Remember Me 인증 ] : RememberMeAuthenticationFilter
Remember-Me ?
- 세션이 만료되고 웹 브라우저가 종료된 이후에도 어플리케이션이 사용자를 기억하는 기능
Remember-Me
쿠키에 대한 Http 요청을 확인한 후에 토큰 기반 인증을 사용해서 유효성을 검사하고 토큰이 검증되면 사용자는 로그인 된다.- 사용자 Life Cycle
- 인증 성공(Remember-Me 쿠키 설정)
- 인증 실패(쿠키가 존재하면 쿠키 무효화)
- 로그아웃(쿠키가 존재하면 쿠키 무효화)
protected void configure(HttpSecurity http) throws Exception {
http.rememberMe()
.rememberMeParameter("remember") // 기본 파라미터명은 remember-me
.tokenValiditySeconds(3600) // Default는 14일
.alwaysRemember(true) // 리멤버미 기능이 활성화되지 않아도 항상 실행
.userDetailsService(userDetailsService) // 리멤버미 기능을 수행할때 시스템의 사용자 계정을 조회할 때 필요한 클래스
;
}
로그인이 되었다는 것은 사용자의 세션이 생성되었고, 그 세션이 성공한 인증객체를 담고 있는 상태이다.
서버는 인증에 성공한 사용자에게 세션을 생성할 때 가지고 있는 JSESSIONID
를 응답헤더에 실어서 보내는 것이다. 그럼 이 클라이언트가 JSESSIONID
를 가지고 있을 것이고, 이 상태에서 클라이언트가 다시 서버에 접속하게 되면 인증을 받지 않아도 되는 이유가 클라이언트가 가지고 온 JSESSIONID
의 아이디와 매칭되는 세션(SecurityContext -> 인증 객체)을 꺼내서 이 사용자가 인증된 사용자인지 판단하고 처리하게 된다.
만약에 클라이언트에서 쿠키(JSESSIONID
)를 제거하고 다시 로그인을 하게 되면 해당 사용자가 처음 로그인한 사용자로 판단할 것이고 다시금 인증을 해야한다.
하지만 remember me
기능을 선택하고 로그인을 하게 되면 리멤버미 인증을 하게 되었으므로 서버는 remember-me라는 이름으로 쿠키를 생성해서 발급한다.
이 때는 사용자의 유저아이디와 패스워드, 쿠키 만료일이 담겨져 있다. 이 기능이 있는 상태에서 동일하게 JSESSIONID
를 제거하고 다시 사이트를 접속하면 인증을 다시 받지 않아도 인증을 거치지 않는다.
그 이유는 JSESSIONID
가 없더하더라도 SpringSecurity에서는 remember-me
라는 쿠키를 가진 값을 가지고 왔을 경우를 체크한다.
rememberMeAuthenticationFilter
에서 이 값을 다시 디코딩 하고 파싱하고 추출해서 userid와 password를 통해서 User 계정을 하나 얻고 이 객체를 통해서 다시금 인증을 시도하고 인증을 성공하게 된다.
> 인증과정
인증을 받은 사용자는 인증 객체가 Security Context
에 저장되어 있다.
Security Context
안의 Authentication
이 null이라는 것은 사용자 세션이 만료되었거나 더이상 세션안에서 Security Context
를 찾지 못하고 인증객체도 없는 경우이다. 이 때 RememberMeAuthenticationFilter
가 동작한다.
(Session Timeout으로 만료되었거나, 브라우저가 종료되어서 세션이 끝나서 SecurityContext에서 인증객체를 찾지 못하는 경우)
다시금 사용자의 인증을 받게 되어서 사용자가 인증이 유지된채로 서버에 접속할 수 있도록 하는 필터이다.
RememberMeAuthenticationFilter
가 동작하는 순서를 정리하자면
- 인증 객체가 없는 경우
- 사용자가 리멤버미 쿠키를 가져오는 경우
에 필터가 정상적으로 작동을 하게 된다.
RememberMeService 인터페이스는 실제로 리멤버미 인증 처리를 하는 두 구현체가 있다.
TokenBasedRememberMeservice
- 메모리에서 실제로 재생한 토큰과, 사용자가 요청할 때 들고온 쿠키의 토큰과 비교해서 인증처리를 한다.
PersistentTokenBasedRememberMeServices
- 영구적인 방식. 디비에서 발급한 토큰과, 사용자가 들고온 온 토큰 값을 비교해서 인증처리를 한다.
사용자의 토큰 쿠키를 추출해서 사용자가 가지고 온 토큰이, remeber-me
라는 이름의 토큰이 존재하는지 검사한다.
리멤버미 토큰이 존재하지 않으면 그다음 필터로 이동하게 된다.(chain.doFilter
)
존재할 경우에는
- decode token해서 정상적인 규칙을 지키고 있는 토큰인지 확인하고
- 이 토큰의 값과 서버에 저장된 토큰의 값이 서로 일치한다면
- 토큰에 포함된 정보 중에서 user 정보가 DB에 존재한다면
- 새로운 Authentication(인증) 객체를 생성하고 이 인증 객체를
- AuthenticationManager에게 전달해서 인증처리를 하게 된다.
'웹 프로그래밍 > [ Spring Security ]' 카테고리의 다른 글
[ Spring Security ] 05. 인증/인가 API의 예외처리 (0) | 2021.12.12 |
---|---|
[ Spring Security ] 04. 인가 API와 표현식 (0) | 2021.12.09 |
[ Spring Security ] 03. 동시 세션제어와 세션 고정보호, 세션 정책 관리 (0) | 2021.12.08 |
[ Spring Security ] 02. 익명 사용자 인증처리 필터 : AnonymousAuthenticationFilter (0) | 2021.12.08 |
[ Spring Security ] 00. LoginForm 인증 API 및 Filter의 이해 (0) | 2021.12.06 |