Spring Boot에 Security를 설정으로 중복 로그인 방지 기능 적용 시 로컬 Session을 사용하지 않고 Redis를 사용 시
세션 정책을 ConcurrentSessionControlAuthenticationStrategy 를 사용하면 중복 로그인 체크가 불안정 해서 세션 정책을
CompositeSessionAuthenticationStrategy를 적용하면 불안정 했던 중복로그인 체크가 안정화가 됐다.
1. SecurityConfig CompositeSessionAuthenticationStrategy, ConcurrentSessionControlAuthenticationStrategy Bean 등록
// 세션 정책 설정 @Bean public CompositeSessionAuthenticationStrategy sessionAuthenticationStrategy(SessionRegistry sessionRegistry) { List<SessionAuthenticationStrategy> strategies = new ArrayList<>(); strategies.add(concurrentSessionControlStrategy(sessionRegistry)); strategies.add(new SessionFixationProtectionStrategy()); strategies.add(new RegisterSessionAuthenticationStrategy(sessionRegistry)); return new CompositeSessionAuthenticationStrategy(strategies); }
@Bean public ConcurrentSessionControlAuthenticationStrategy concurrentSessionControlStrategy(SessionRegistry sessionRegistry) { ConcurrentSessionControlAuthenticationStrategy strategy = new ConcurrentSessionControlAuthenticationStrategy(sessionRegistry); strategy.setMaximumSessions(1); strategy.setExceptionIfMaximumExceeded(false); return strategy; }
|
2. SessionExpiredStrategy Class Component 구현
SessionExpiredStrategy Class는 먼저 로그인 한 유저가 세션이 Expired 될때 후처리를 할 수 있는 Class이다.
@Component public class CustomSessionExpiredStrategy implements SessionInformationExpiredStrategy {
@Override public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException { HttpServletResponse response = event.getResponse(); HttpServletRequest request = event.getRequest(); response.sendRedirect("이동URL?expired-session=true"); }
}
|
3. SecurityConfig SecurityFilterChain 수정
//중복 로그인 Custom Session Expired private final CustomSessionExpiredStrategy customSessionExpiredStrategy;
@Bean public SecurityFilterChain filterChain( HttpSecurity http , AuthenticationManager authenticationManager, CompositeSessionAuthenticationStrategy sessionStrategy) throws Exception { . . . . // 세션 관리 설정 http.sessionManagement( sessionManagement -> sessionManagement .sessionCreationPolicy( SessionCreationPolicy.IF_REQUIRED ) .enableSessionUrlRewriting( false ) .sessionFixation().changeSessionId() .maximumSessions( 1 ) .expiredSessionStrategy(customSessionExpiredStrategy) //.expiredUrl( "이동URL?invalid-session=true" ) //CustomSessionExpiredStrategy 에서 처리하기 대문에 주석 .maxSessionsPreventsLogin( false ) .sessionRegistry( sessionRegistry) );
// Filter 적용 시 SessionRegistry를 필터에 적용을 해줘야 정책이 반영된다. http.addFilterAfter( customAuthenticationFilter( authenticationManager, sessionStrategy ) , UsernamePasswordAuthenticationFilter.class );
return http.build(); }
@Bean public CustomAuthenticationFilter customAuthenticationFilter ( AuthenticationManager authenticationManager, CompositeSessionAuthenticationStrategy sessionStrategy) throws Exception {
CustomAuthenticationFilter filter = new CustomAuthenticationFilter (); filter.setAuthenticationManager( authenticationManager ); filter.setFilterProcessesUrl( "/member/login-cert-processing" ); filter.setUsernameParameter( "mbrId" ); filter.setPasswordParameter( "mbrPswd" ); filter.setAuthenticationSuccessHandler( customAuthenticationSuccessHandler() ); filter.setAuthenticationFailureHandler( customAuthenticationFailureHandler() ); filter.setSessionAuthenticationStrategy(sessionStrategy); // 세션 관리 전략 설정
return filter;
}
|
ConcurrentSessionControlAuthenticationStrategy나 CompositeSessionAuthenticationStrategy 둘다 기본적으로 Session 개수를 제한 하는 정책을 수립 할 수 있는데 ConcurrentSessionControlAuthenticationStrategy 정책이 왜 Redis에서 불안정 한지 잘은 모르겠다.
이전에는 격지 않았는데 이번에 네이버클라우드 Redis 서비스, Wildfly를 사용을 하면서 불안정 한건지는 모르겠지만
중복로그인을 처리 할 때 중복체크가 불안정하면 CompositeSessionAuthenticationStrategy 정책으로 변경하면 된다.
개인적으로 여러 세션 전략을 적용 할 수 있는 CompositeSessionAuthenticationStrategy를 사용하는 것이 좋을거 같다.