Spring Session
Spring Session
사용자 세션 정보 관리를 위한 API 와 구현체 제공
어플리케이션 컨테이너에 종속되지 않고 클러스터링 된 세션 지원
HttpSession
WebSocket
WebSession
크게 3가지의 구현체를 제공한다.
왜 클러스터링된 세션이 필요한지
일반적으로 세션은 각 서버 메모리에 저장.
분산 환경에서는
서버 #1 세션이
서버 #2 로 가는 경우 세션이 사라져버린다.
해결방안
공유 저장소로 세션 관리
공유 세션 저장소(Shared Session Storage) 도입 필
모든 서버가 같은 저장소 (Redis, DB 등) 을 바라봄
서버 #2 에서 세션 데이터를 요청해도 문제없음.
어떤식으로 해결하는건지?
스프링 세션
어플리케이션과 세션 관리 사이에
추상화 계층 생성
.이를 통해 다양한 저장소(RDB, NoSQL, Redis 등) 저장이 가능
언제 쓰나
분산 웹 어플리케이션 ~ MSA 서버
확장성 문제 해결
동시 사용자가 많은 대형 어플리케이션에서 서버 메모리에 세션 저장하면 한계가 있음
별도의 세션 저장소가 필요하다
백업 + 복구
Spring Session Modules
spring-session 레포지터리
코어 모듈
몽고 DB 모듈
레디스 모듈
JDBC 모듈
Hazelcast 모듈
자바 오픈소스 인메모리 데이터 그리드
이 있음.
spring-session-data-geode 페포지터리
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 관련
쿠키 기반으로 동작한다.
쿠키에
나는 누구야~
라고 정보를 저장하고쿠키를 브라우저에서만 저장됨.
서버에서는 추적이 안된다
쿠키가 유효하면 통과시키고 로그인하라고하면 한다..
문제점
클러스터된 서버의 경우 쿠키를 공유하지 못하여 remember-me 기능이 사용이 되지 않는다.
Spring Session 기반 Spring Security
서버 측 데이터 관리
remember-me 정보를 레디스 같은 인메모리에 저장함.
모든 서버에서 세션 데이터를 동일한 환경에서 사용이 가능하다
유연한 쿠키 관리가 가능
요 내용은 일반 Spring Security 에서도 가능하지 않나 생각됨..
왜 굳이 스프링 공식문서에 추가되어 있는지는 모르겠음.
Spring Session Remember-me 기능은 쿠키 만료가 INTEGER.MAX_VALUE 로 설정한다고 한다.쿠키의 유효기간이 무한대세션 갱신 문제 해결 가능세션 갱신 문제?사용자가 로그인한 상태에서 세션 갱신되는 경우서버는 새로운 세션데이터를 만든다.쿠키의 유효기간은 갱신되지 않아사용자가 다시 로그인을 해야하는 문제가 있음.
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);
}
}
세션 제한 설정
maximumSessions 을 통하여 동시에 가질 수 있는 세션을 2개로 제한..
세션 클러스터링을 지원
SpringSessionBackedSessionRegistry 을 사용해 여러 서버(클러스터) 환경에서도 해당 규칙이 적용
다른 서버에서 호출이 되더라도, 사용자가 이미 2개의 세션을 가지고 있는지 여부를 확인이 가능해짐.
어떻게 확인하는걸까?
레디스 같은 경우
keys spring:session:index:org.springframework.session.FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME:<username>*
이런식으로 특정 키 값에 세션이 어떤 사용자와 연결되어 있는지 확인함.
사용자가 2개의 세션을 활성화한 경우 키가 2개가 나오게 된다.