Spring Boot/Spring Security

[Spring Security] Remember Me 인증, RememberMeAuthenticationFilter

수수한개발자 2022. 6. 29.
728x90

Remember Me 인증

우리가 일반적인 웹 애플리케이션에 접속할 때 로그인 유지하기가 있을 것이다.

그 기능은 쿠키로 구현하는것인데. 스프링 시큐리티에서는 이 기능 또한 제공하고 있다.

 

Remember me 적용하기

protected void configure(HttpSecurity http) throws Exception {
    http.rememberMe()
    .rememberMeParameter(“remember”) // 기본 파라미터명은 remember-me
    .tokenValiditySeconds(3600) // Default 는 14일
    .alwaysRemember(true) // 리멤버 미 기능이 활성화되지 않아도 항상 실행
    .userDetailsService(userDetailsService)
}

위와 같이 http.rememberMe()라는 api 사용하게 되면 로그인 창에 Remember me on this computer 체크박스가 생긴다.

   . alwaysRemember(true) // 리멤버 미 기능이 활성화되지 않아도 항상 실행 일반적이라면 false 하는 게 맞다.
   . userDetailsService(userDetailsService) // 사용자 정보를 조회하는 클래스

 

체크를 안 하고 로그인을 해줍니다. 성공을 했다 == 인증을 성공했다는 건데 그러면 세션이 생성되고 

그 세션이 성공한 인증 객체를 담고 있는 상태입니다.

세션을 생성할 때 JSESSIONID를 줍니다. 근데 여기서 세션을 삭제하고 다시 루트 페이지로 들어가면 로그인 페이지가 다시 생깁니다. 왜냐하면 세션에 인증정보가 있는데 세션이 없어졌기 때문에 인증을 받지 않은 사용자라고 인식을 해서입니다.

다시 로그인 페이지로 와서 Remember me를 체크하고 로그인해줍시다.

그러면 위와 같이 remember-me라는 쿠키가 생깁니다. 

이러고 JSESSIONID를 삭제해도 우리는 로그아웃 처리가 되지 않습니다. 왜냐하면 스프링 시큐리티는 리멤버 미라는 쿠키라는 걸 체크합니다. request header에 remember-me라는 쿠키가 있다면 다시 디코드 하고 파싱 해서 유저 아이디와 패스워드를 통해 유저 객체를 얻고 다시 인증을 시도해서 인증에 성공하게 됩니다. 이런 기능이 rememberMe 기능을 통해서 이루어지게 되고 이 유저 객체가 다시 JSESSIONID에 담기게 됩니다. 이런 것들이 RememberMeAuthenticationFilter로 이루어지는데 이 필터에 대해서 알아보겠습니다.

RememberMeAuthenticationFilter

 

RememberMeAuthenticationFilter가 작동하는데 작동하는 조건은 2가지 경우가 있다

첫 번째는 Authentication객체가 null일 때이다.

왜냐하면 Authentication 객체는 Security Context에 저장되어있는데 SecurityContext에 이미 null 아닌 인증 객체가 있으면 인증된 사용자이기 때문에 또다시 인증할 필요가 없기 때문입니다.

두 번째는 remember-me 쿠키를 가지고 있을 때이다.

이러한 경우에 최초의 form 인증한 경우에 remember쿠키를 발급했을 경우이다. 

세션 타임 아웃이나, 브라우저가 닫혔을 경우 그 사용자의 세션은 무효화되지만 request header에 rememberme 쿠키값을 가지고 서버에 접속한 경우 서버가 rememberme쿠키를 가지고 인증을 시도한다.

세션이 만료되었고 remberme쿠키를 가지고 있다 가정하자.

RememberMeService 구현체가 두 개 있는데

TokenBassedRememberMeService = 메모리에서 제작한 토큰과 사용자가 요청할 때 들고 온 토큰과 비교해 인증처리를 한다. 기본적으로 14일 만료기간이 있다.

PersistentTokenBassedRememberMeService =  디비에 있는 토큰과 사용자 토큰과 비교하여 인증한다.
RememberMeService 가 토큰을 추출합니다.

Token쿠키 추출

토큰이 존재하는가 , 토큰 이름이 remember-me라는 이름의 토큰인지를 검사하게 됩니다.

존재하게 되면 진행되고 존재하지 않으면 그다음 Filter로 이동하게 됩니다.

존재하면 토큰 형식이 있는데 Decode Token 포맷이 정상적으로 규칙을 지키고 있는 토큰인지 정상인지 판단하게 됩니다.

정상 유무를 체크해서 정상이 아니면 예외, 정상이면 진행

사용자 토큰과 서버에 저장된 토큰이 서로 일치하는지 검증하게 됩니다.

일치하면 진행, 아니면 예외

토큰이 일치하면 User계정이 존재하면 DB에 저장된 유저 정보를 조회 있으면 진행, 없으면 예외

User정보가 있으면 새로운 Authentication 인증 객체를 remember me 라는 이름으로 생성합니다.

그 인증객체를 AuthenticationManager가 인증 처리한다.

사용자 정보가 없으면 rememberMe쿠키로 인증처리를 대신한다.

계속적으로 세션이 만료되었어도 인증을 유지할 수 있도록 하는 필터이다.

728x90

댓글