• Feed
  • Explore
  • Ranking
/

    Spring Session

    Spring Session
    박
    박상준
    2024.12.09
    ·
    9 min read

    Spring Session

    • 사용자 세션 정보 관리를 위한 API 와 구현체 제공

    • 어플리케이션 컨테이너에 종속되지 않고 클러스터링 된 세션 지원

    HttpSession

    WebSocket

    WebSession

    크게 3가지의 구현체를 제공한다.

    왜 클러스터링된 세션이 필요한지

    • 일반적으로 세션은 각 서버 메모리에 저장.

    • 분산 환경에서는

      • 서버 #1 세션이

      • 서버 #2 로 가는 경우 세션이 사라져버린다.

    해결방안

    • 공유 저장소로 세션 관리

      • 공유 세션 저장소(Shared Session Storage) 도입 필

      • 모든 서버가 같은 저장소 (Redis, DB 등) 을 바라봄

      • 서버 #2 에서 세션 데이터를 요청해도 문제없음.

    어떤식으로 해결하는건지?

    • 스프링 세션

      • 어플리케이션과 세션 관리 사이에 추상화 계층 생성.

      • 이를 통해 다양한 저장소(RDB, NoSQL, Redis 등) 저장이 가능

    언제 쓰나

    1. 분산 웹 어플리케이션 ~ MSA 서버

    2. 확장성 문제 해결

      1. 동시 사용자가 많은 대형 어플리케이션에서 서버 메모리에 세션 저장하면 한계가 있음

      2. 별도의 세션 저장소가 필요하다

    3. 백업 + 복구

    Spring Session Modules

    1. spring-session 레포지터리

      1. 코어 모듈

      2. 몽고 DB 모듈

      3. 레디스 모듈

      4. JDBC 모듈

      5. Hazelcast 모듈

        1. 자바 오픈소스 인메모리 데이터 그리드

      이 있음.

    2. spring-session-data-geode 페포지터리

    3. spring-session-bom 레포지터리

    Spring Session + HttpSession

    HttpSession

    • 손님의 주문 정보를 담은 하나의 노트라고 보면 된다.

    • 단일 어플리케이션의 경우

      • 해당 추상체를 사용해도 문제없지만

    • 매장마다 고유의 주문 정보를 담아서 사용하기는 불가능하다.

      • 다른 매장에 주문정보를 담아서 간다고 하더라도

      • 해당 매장에서는 그 주문정보와 양식이 달라 종업원이 처리하기가 힘들어진다.

    • 그래서 등장한 것이

    Spring Session 인데

    • 어디로 가든지 주문 정보가 공유되는 시스템을 손쉽게 구축이 가능해진다.

    Spring Session 의 장점

    • 클러스터링을 지원

      • 노트대신 클라우드 시스템으로 메모 내용이 공유된다고 생각하면 된다

    • RESTful 지원

      • 헤더에 세션 ID 를 넣어서 관리가 가능해진다.

      • 원래 단일 어플리케이션의 경우 JSESSION - 쿠키로 관리하는게

      • MSA 구조에서는 API 헤더를 통해 정보가 오가게 된다.

    Redis 와 연동

    @EnableRedisHttpSession 
    public class Config {
    
    	@Bean
    	public LettuceConnectionFactory connectionFactory() {
    		return new LettuceConnectionFactory(); 
    	}
    
    }
    
    
    • @EnableRedisHttpSession 같은 경우

      • 레디스를 공유 세션 저장소로 사용할 것입니다!

      • 의 선언이다

    • LettuceConnectionFactory 의 경우

      • Redis 에 연결하는 코드로서

      • local:6379 로 정의되어 있는 경우 해당 포트에 연결을 시도한다

      • 만약 별도의 세션 저장소 url 이 있다면 해당 위치에 저장을 시도하면 된다.

    Spring Configuration 이 추가적으로 해줘야하는 일이 있음.

    • tomcat 의 경우 기본적으로 HTTP SESSION 을 사용하려고하기에

      • 별도로 Spring Session 을 사용하도록 명령을 내려줘야한다.

    • springSessionRepositoryFilter 으로 해당 명령을 내릴 수 있는데

      • 모든 요청(Request) 에 대해 HttpSession 을 새롭게 SpringSession 으로 변경한다.

    • 여기서 등장하는 개념이 Initializer 이다.

      public class Initializer extends AbstractHttpSessionApplicationInitializer { 
      	public Initializer() {
      		super(Config.class); 
      	}
      }
      
      • AbstractHttpSessionApplicationInitializer 을 상속받음으로서

        • Tomcat 에게 Config.class 를 사용해서 springSessionRepositoryFilter 를 만들라고 지시를 한다.

        • 해당 필터생성 후 → 모든 HTTP 요청이 필터를 거쳐서 HttpSession → Spring Session 으로 변경된다.

    Spring Security + Spring Session

    • spring session 에서 는 spring security 에 있는 rememberMe 관리가 가능함.

    기존 spring security 관련

    1. 쿠키 기반으로 동작한다.

      1. 쿠키에 나는 누구야~ 라고 정보를 저장하고

      2. 쿠키를 브라우저에서만 저장됨.

    2. 서버에서는 추적이 안된다

      1. 쿠키가 유효하면 통과시키고 로그인하라고하면 한다..

    문제점

    • 클러스터된 서버의 경우 쿠키를 공유하지 못하여 remember-me 기능이 사용이 되지 않는다.

    Spring Session 기반 Spring Security

    1. 서버 측 데이터 관리

      1. remember-me 정보를 레디스 같은 인메모리에 저장함.

      2. 모든 서버에서 세션 데이터를 동일한 환경에서 사용이 가능하다

    2. 유연한 쿠키 관리가 가능

      요 내용은 일반 Spring Security 에서도 가능하지 않나 생각됨..

      왜 굳이 스프링 공식문서에 추가되어 있는지는 모르겠음.

      1. Spring Session Remember-me 기능은 쿠키 만료가 INTEGER.MAX_VALUE 로 설정한다고 한다.

      2. 쿠키의 유효기간이 무한대

      3. 세션 갱신 문제 해결 가능

        세션 갱신 문제?

        • 사용자가 로그인한 상태에서 세션 갱신되는 경우

        • 서버는 새로운 세션데이터를 만든다.

        • 쿠키의 유효기간은 갱신되지 않아

          • 사용자가 다시 로그인을 해야하는 문제가 있음.

    User Concurrent Session Control

    동시 접속 방지 기능

    • 한 브라우저에서 로그인 + 다른 브라우저에서 또 로그인한 경우

    • 해당 동시접속 세션에 대해 제어가 가능하다.

    GPT 코드 예시

    @Configuration
    public class SecurityConfiguration<S extends Session> extends WebSecurityConfigurerAdapter {
    
    	@Autowired
    	private FindByIndexNameSessionRepository<S> sessionRepository;
    
    	@Override
    	protected void configure(HttpSecurity http) throws Exception {
    		http
    			// 추가 설정...
    			.sessionManagement((sessionManagement) -> sessionManagement
    				.maximumSessions(2)  // 최대 2개의 세션만 허용
    				.sessionRegistry(sessionRegistry())
    			);
    	}
    
    	@Bean
    	public SpringSessionBackedSessionRegistry<S> sessionRegistry() {
    		return new SpringSessionBackedSessionRegistry<>(this.sessionRepository);
    	}
    }
    
    1. 세션 제한 설정

      • maximumSessions 을 통하여 동시에 가질 수 있는 세션을 2개로 제한..

    2. 세션 클러스터링을 지원

      1. SpringSessionBackedSessionRegistry 을 사용해 여러 서버(클러스터) 환경에서도 해당 규칙이 적용

      2. 다른 서버에서 호출이 되더라도, 사용자가 이미 2개의 세션을 가지고 있는지 여부를 확인이 가능해짐.

      어떻게 확인하는걸까?

      • 레디스 같은 경우

        keys spring:session:index:org.springframework.session.FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME:<username>*
        
        • 이런식으로 특정 키 값에 세션이 어떤 사용자와 연결되어 있는지 확인함.

        • 사용자가 2개의 세션을 활성화한 경우 키가 2개가 나오게 된다.