본문 바로가기

개발중/Spring Boot & Redis

Spring Security에서 Redis를 사용하면서 겪은 SessionRegistry 문제

728x90
반응형

조건

  • 시스템은 중복 로그인이 2회까지 가능합니다.
  • Api pod 는 2개가 실행중입니다.

 

실패 시나리오

 

1. Pod A 에 test@com 계정이 로그인을 시도했고 성공했습니다.

 

2. Pod A 에 test@com 계정이 로그인을 시도했고 성공했습니다.

( 이 때 까지는  중복 로그인이 허용되는 범위입니다. )

3. Pod B 에 test@com 계정이 로그인을 시도했고 중복 로그인이 허용되는 범위를 초과했습니다.

( 하지만 로그인 성공했습니다. )

 

 

이슈

Redis 에서 통합적인 session 관리를 하므로 Pod B 에서 시도한 3회차 로그인 시도에서는 중복로그인이 허용되는 범위를 초과했기 때문에 중복 로그인이 실패해야합니다.

내가 생각한 바람직한 결과


Pod 2 에서 로그인된 계정을 판단할 때 Pod 1 에 있는 두 개의 계정에 대한 인식을 못하고 있습니다.

 

Spring Redis Session 설정을 완료했음에도 불구하고 Spring Security 에서 사용하는 SessionRegistry 는 아직 Spring Session 에서 관리되고 있는 듯합니다.

 

해결 방안

아래와 같이 @EnableRedisHttpSession 선언을 해준 후 SessionRepository 를 Bean 으로 등록할 때 Redis 를 사용하겠다고 선언하면 됩니다.

 

@EnableRedisHttpSession
public class RedisSessionConfiguration {

    @Bean
    public SessionRegistry springSessionBackedSessionRegistry(RedisIndexedSessionRepository redisIndexedSessionRepository) {
        return new SpringSessionBackedSessionRegistry<>(redisIndexedSessionRepository);
    }
}

 

그럼 아래와 같이 SessionRepository  를 통해서 중복 로그인 체크를 Redis 에서 관리하기 때문에 Pod 간의 Security Session Storage 가 통합되지 않아 발생하는 문제는 해결이 됩니다.

 

private final SessionRegistry sessionRegistry;

public Authentication authenticate(Authentication auth) {
    ...
    
    /** 중복로그인 체크 **/
    List<SessionInformation> allSessions = sessionRegistry.getAllSessions(userDetails.getUsername(), false);

    int sessionSize = allSessions.size();

    if (company.getDuplicateLoginCnt() - sessionSize == 0) {
        throw new CustomAuthenticationException(ExceptionType.EXCEED_DUPLICATION_LOGIN);
    }
    
    ...
}

 

너무나 당연히 SecurityFilterChain 에 sessionRegistory 는 설정해줘야합니다.

 

private SessionRegistry sessionRegistry;

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) {

   ...
   
   http.sessionManagement()
    .maximumSessions(1)
    .sessionRegistry(sessionRegistry);

   ...
   
}
728x90
반응형