Remember Me 설정

@Configuration
@EnableWebSecurity
public class SecurityConfig {

	@Bean
	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

		//region rememberMe
		http
			.rememberMe()
			.rememberMeParameter("remember")  // 기본 파라미터명은 remember-me
			.tokenValiditySeconds(3600)  // 유지 시간 Default 는 14일
			.alwaysRemember(false) // 리멤버 미 기능을 활성화하지 않아도 계속 실행할 것인지
		//endregion

		;
		return http.build();
	}

}

 

 


 

 

전체 코드

@Configuration
@EnableWebSecurity
public class SecurityConfig {

	@Bean
	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
		http
			.authorizeRequests()
			.anyRequest().authenticated();
		http
			.formLogin()
			// .loginPage("/login")             //사용자 정의 로그인 페이지

			//region 핸들러없이 바로 이동페이지 설정
			// .defaultSuccessUrl("/")                 // 로그인 성공 후 이동 페이지
			// .failureUrl("/login")             // 로그인 실패 후 이동페이지
			//endregion

			//region 제공해주는 로그인페이지 파라마터 name 및 Action 셋팅
			.usernameParameter("userId")         // 아이디 파라미터명 설정
			.passwordParameter("passwd")         //패스워드 파라미터명 설정
			.loginProcessingUrl("/login_proc")   //로그인 form Action url 설정
			//endregion

			// 로그인 성공후 핸들러
			.successHandler(new AuthenticationSuccessHandler() {
				@Override
				public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
					System.out.println("authentication" + authentication.getName());
					response.sendRedirect("/");
				}
			})

			// 로그인 실패 후 핸들러
			.failureHandler(new AuthenticationFailureHandler() {
				@Override
				public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
					System.out.println("exception" + exception.getMessage());
					response.sendRedirect("/login");
				}
			})
			.permitAll();  //로그인페이지를 모든 사용자가 접근 가능하도록 설정

		//region logout
		http
			.logout()                                     //Post로 진행해야함
			.logoutUrl("/logout")                         // 로그아웃 처리 url
			.logoutSuccessUrl("/login")                  // 로그아웃 성공 후 이동페이지
			.addLogoutHandler(new LogoutHandler() {      // 로그아웃 핸들러
				@Override
				public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
					HttpSession session = request.getSession();
					session.invalidate();
				}
			})
			.logoutSuccessHandler(new LogoutSuccessHandler() {         // 로그아웃 성공 후 핸들러
				@Override
				public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
					response.sendRedirect("/login");
				}
			})
			.deleteCookies("JSESSIONID", "remember-me"); // 로그아웃 후 쿠키 삭제
		// endregion

		//region rememberMe
		http
			.rememberMe()
			.rememberMeParameter("remember")  // 기본 파라미터명은 remember-me
			.tokenValiditySeconds(3600)  // 유지 시간 Default 는 14일
			.alwaysRemember(false) // 리멤버 미 기능을 활성화하지 않아도 계속 실행할 것인지
		//endregion

		;
		return http.build();
	}

}

 

 

화면 플로우

rememberMe 를 설정하면 아래와 같이 로그인 폼에 Remember me on this computer. 라는 체크 박스가 생긴다. 체크를 해주고 로그인을 하면 JSESSIONID이 삭제되어도 로그인유지가 가능하다.

 

그 이유는 remember-,me 라는 쿠키가 생겼기 때문인데. 설정해준 기간만큼 유지가 가능하다.

 

실제로 JSESSIONID를 삭제 후 새로고침을 해도 유지가 되는 것을 확인 할 수 있다.

 

 

코드 플로우

AbstractAuthenticationProcessingFilter.class의 successfulAuthentication() 에서 10번째 줄을 보면 loginSuccess 메소드가 실행된다. 

protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
        Authentication authResult) throws IOException, ServletException {
    SecurityContext context = SecurityContextHolder.createEmptyContext();
    context.setAuthentication(authResult);
    SecurityContextHolder.setContext(context);
    this.securityContextRepository.saveContext(context, request, response);
    if (this.logger.isDebugEnabled()) {
        this.logger.debug(LogMessage.format("Set SecurityContextHolder to %s", authResult));
    }
    this.rememberMeServices.loginSuccess(request, response, authResult);
    if (this.eventPublisher != null) {
        this.eventPublisher.publishEvent(new InteractiveAuthenticationSuccessEvent(authResult, this.getClass()));
    }
    this.successHandler.onAuthenticationSuccess(request, response, authResult);
}

 

타고 들어가면  rememeber-me 쿠키가 만들어져 Response에 담게된다.

	@Override
	public void onLoginSuccess(HttpServletRequest request, HttpServletResponse response,
			Authentication successfulAuthentication) {
		String username = retrieveUserName(successfulAuthentication);
		String password = retrievePassword(successfulAuthentication);
		// If unable to find a username and password, just abort as
		// TokenBasedRememberMeServices is
		// unable to construct a valid token in this case.
		if (!StringUtils.hasLength(username)) {
			this.logger.debug("Unable to retrieve username");
			return;
		}
		if (!StringUtils.hasLength(password)) {
			UserDetails user = getUserDetailsService().loadUserByUsername(username);
			password = user.getPassword();
			if (!StringUtils.hasLength(password)) {
				this.logger.debug("Unable to obtain password for user: " + username);
				return;
			}
		}
		int tokenLifetime = calculateLoginLifetime(request, successfulAuthentication);
		long expiryTime = System.currentTimeMillis();
		// SEC-949
		expiryTime += 1000L * ((tokenLifetime < 0) ? TWO_WEEKS_S : tokenLifetime);
		String signatureValue = makeTokenSignature(expiryTime, username, password);
		setCookie(new String[] { username, Long.toString(expiryTime), signatureValue }, tokenLifetime, request,
				response);
		if (this.logger.isDebugEnabled()) {
			this.logger.debug(
					"Added remember-me cookie for user '" + username + "', expiry: '" + new Date(expiryTime) + "'");
		}
	}
복사했습니다!