Spring을 사용하면 Security에서 손쉽게 중복 로그인 방지 설정을 할 수 있다.
@Bean
public SecurityFilterChain filterChain(HttpSecurity http, AuthenticationManager authenticationManager ,ConcurrentSessionControlAuthenticationStrategy sessionStrategy) throws Exception { .....생략 // 세션 관리 설정 http.sessionManagement(sessionManagement -> sessionManagement .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) .enableSessionUrlRewriting(false) .sessionFixation().changeSessionId() .maximumSessions(1) .expiredUrl("/login?invalid-session=true") .maxSessionsPreventsLogin(false) .sessionRegistry(sessionRegistry()) ); return http.build(); } |
1. sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
- 역할:
- Spring Security가 세션을 생성하는 시점을 정의합니다.
- SessionCreationPolicy 옵션:
- ALWAYS: 요청마다 새 세션을 강제로 생성.
- NEVER: Spring Security가 세션을 생성하지 않지만 이미 존재하는 세션은 사용.
- IF_REQUIRED: 인증이 필요하면 세션을 생성 (기본값).
- STATELESS: 세션을 전혀 생성하지 않음. JWT 기반 인증 같은 무상태(stateless) 애플리케이션에서 사용.
- 적용 효과:
- 이 설정으로 세션은 "필요할 때만" 생성되며, 세션이 없는 상태에서 인증 요청이 들어오면 새로 생성됩니다.
2. enableSessionUrlRewriting(false)
- 역할:
- 세션 ID를 URL에 추가하는 것을 허용할지 여부를 설정.
- 배경:
- URL에 세션 ID가 포함되면 브라우저 간 세션 공유, 세션 하이재킹(Session Hijacking) 같은 보안 문제가 발생할 수 있음.
- 적용 효과:
- false: URL에 세션 ID를 포함하지 않음. 쿠키 기반 세션 유지만 허용.
- 보안 강화를 위해 보통 false로 설정.
3. sessionFixation().changeSessionId()
- 역할:
- 인증 과정에서 세션 고정(Session Fixation) 공격을 방지하기 위해 기존 세션 ID를 변경.
- 배경:
- 공격자가 사용자의 세션 ID를 미리 예측하거나 가로채서 악의적인 작업을 수행할 수 있음.
- 적용 효과:
- changeSessionId(): 기존 세션의 속성을 유지하면서 새로운 세션 ID를 생성.
- newSession(): 기존 세션을 무효화하고 새로운 세션 생성.
- none(): 세션 ID를 변경하지 않음 (비권장).
- 권장:
- changeSessionId()는 보안성과 성능의 균형이 맞아 자주 사용됨.
4. maximumSessions(1)
- 역할:
- 한 사용자당 동시에 유지 가능한 세션 수를 제한.
- 적용 효과:
- 여기서는 1로 설정되어, 한 사용자가 한 번에 하나의 세션만 가질 수 있음.
- 다른 브라우저나 기기에서 동일한 계정으로 로그인하면 이전 세션이 만료됨.
5. expiredUrl("/login?invalid-session=true")
- 역할:
- 사용자의 세션이 만료되었을 때 리디렉션될 URL을 설정.
- 적용 효과:
- 예를 들어, 동일한 계정으로 다른 브라우저에서 로그인하면 기존 세션은 만료되고 /login?invalid-session=true로 리디렉션됩니다.
- 사용자 경험을 개선하기 위해 "세션 만료됨" 메시지를 이 URL에서 처리할 수 있음.
6. maxSessionsPreventsLogin(false)
- 역할:
- 세션 제한을 초과했을 때 새로운 로그인을 허용할지 결정.
- 적용 효과:
- false: 새로운 로그인 요청을 허용. 기존 세션은 만료됨.
- true: 새로운 로그인 요청을 차단. "이미 최대 세션 수에 도달했습니다" 같은 에러를 반환.
- 권장 사용:
- 일반적으로 false로 설정하여 사용자가 다른 기기에서 로그인할 수 있도록 함.
7. sessionRegistry(sessionRegistry())
- 역할:
- SessionRegistry는 활성 세션을 추적하고 관리하는 데 사용됩니다.
- 이 설정은 Spring Security의 동시 세션 제어(Concurrent Session Control)에 필요.
- 적용 효과:
- 사용자당 활성 세션 목록을 유지하며, 특정 사용자의 모든 세션을 만료시키거나, 만료된 세션 정보를 추적할 수 있음.
- Spring Security의 SessionRegistryImpl을 기본 구현으로 사용.
적용 예
- 사용자가 이미 로그인된 상태에서 다른 브라우저에서 로그인:
- 기존 세션은 만료되고 /login?invalid-session=true로 리디렉션.
- 새로운 세션이 생성되어 인증이 유지됨.
- 사용자가 최대 세션 제한을 초과:
- maxSessionsPreventsLogin(false)로 인해 새 로그인이 허용되고, 이전 세션은 종료됨.
필터를 사용 하게 되면 필터에 session registry를 별도로 설정을 해줘야 한다.
1. SecurityConfig에 ConcurrentSessionControlAuthenticationStrategy Bean 추가
@Bean
public ConcurrentSessionControlAuthenticationStrategy concurrentSessionControlStrategy(SessionRegistry sessionRegistry) { ConcurrentSessionControlAuthenticationStrategy strategy = new ConcurrentSessionControlAuthenticationStrategy(sessionRegistry); strategy.setMaximumSessions(1); strategy.setExceptionIfMaximumExceeded(false); return strategy; } |
2. SecurityConfig에 filterChain에 ConcurrentSessionControlAuthenticationStrategy sessionStrategy 추가하고 Filter에 전달
@Bean public SecurityFilterChain filterChain(HttpSecurity http, AuthenticationManager authenticationManager ,ConcurrentSessionControlAuthenticationStrategy sessionStrategy) throws Exception { .....생략 // 세션 관리 설정 http.sessionManagement(sessionManagement -> sessionManagement .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) .enableSessionUrlRewriting(false) .sessionFixation().changeSessionId() .maximumSessions(1) .expiredUrl("/login?invalid-session=true") .maxSessionsPreventsLogin(false) .sessionRegistry(sessionRegistry()) ); http.addFilterBefore(CustomAuthenticationFilter(authenticationManager, sessionStrategy), UsernamePasswordAuthenticationFilter.class);
return http.build(); } @Bean
public CustomAuthenticationFilter CustomAuthenticationFilter(AuthenticationManager authenticationManager ,ConcurrentSessionControlAuthenticationStrategy sessionStrategy) { KsignGpkiCertAuthenticationFilter filter = new KsignGpkiCertAuthenticationFilter(); filter.setAuthenticationManager(authenticationManager); // AuthenticationManager 설정 filter.setFilterProcessesUrl("/member/ksign-gpki-login-processing"); // 필터가 처리할 URL 설정 filter.setAuthenticationSuccessHandler(customAuthenticationSuccessHandler()); // 인증 성공 핸들러 설정 filter.setAuthenticationFailureHandler(customAuthenticationFailureHandler()); // 인증 실패 핸들러 설정 filter.setSessionAuthenticationStrategy(sessionStrategy); // 세션 관리 전략 설정 return filter; } |
필터 등록 시 세션 관리 전략을 설정하지 않으면 중복 로그인 방지가 작동하지 않는다.
'Development Story > Java' 카테고리의 다른 글
Spring Boot Redis Session Timeout 설정 (1) | 2024.12.27 |
---|---|
Spring Boot Security + Redis 중복 로그인 방지 + 중복 알림 (0) | 2024.12.27 |
Spring Boot Redis 설정 (1) | 2024.11.18 |
Transaction Log tmlog 설정 (2) | 2024.09.27 |
네이버 클라우드 Ncp Cloud Out Bound Mailer spring구현 (1) | 2024.09.24 |