SessionManagementFilter
- 동시 세션 제어 : 동일 계정의 최대 허용 세션 수 초과여부 확인 및 처리
- 세션 보호 : 로그인시 새로운 세션 생성하여 기존 세션 사용 못하도록 함
- 세션 생정시 이벤트 발생
ConcurrentSessionFilter
- 매 요청마다 세션의 만료 여부를 실시간으로 체크하여 중복로그인 등으로 만료된 세션 접근 차단
HttpSessionEventPublisher
- 서블릿 컨테이너(예 : 톰캣) 에서 발생하는 HttpSession 이벤트 감지하여 Spring 이벤트로 변환 하고 발행함
- Spring 에서는 서블릿 컨테이너 동작을 알 수 없기 때문에 중간에 다리를 놓아주는 게 필요하다.
- 동시세션 제어 기능을 정확하게 동작시키기 위해 반드시 필요.
- SessionCreationEvent
- SessionDestroyedEvent
SessionInformationExpiredStrategy
- 세션이 만료 되었을때 클라이언트에 응답을 하기 위해 사용. 이벤트를 감지하여 동작하므로 HttpSessionEventPublisher가 반드시 필요하다.
- 세션이 있었으나 만료 되었을 경우에 해당한다.
InvalidSessionStrategy
- 세션이 존재하지 않거나 없을 경우 처리 한다. 위의 SessionInformationExpiredStrategy 와 비슷하나 의미가 다르다.
SessionRegistry
- 현재 로그인 사용자의 세션을 추척하는 저장소로, 사용자가 몇개의 세션을 가지고 있는지, 유효한지 등을 판단할때 사용함.
- HttpSessionEventPublisher 가 반드시 필요하다. 여기서 발생한 이벤트를 이용한다.
- Spring 에서 저장하는 부분
- 톰캣 같은 서블릿 컨테이너에서 세션아이디를 별도로 관리하나, SessionId를 key로 하여 map에서 관리 하기 때문에 비즈니스 로직 (예 : A 사용자가 가진 세션ID) 관점에서 세션아이디를 찾거나 할 수 없어 따로 스프링에서 저장하여 활용함.
SecurityFilterChain 에 다음과 같이 설정 할 수 있다.
...
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(x -> x.anyRequest()
.permitAll()
)
.....
.sessionManagement(session ->
session.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.invalidSessionStrategy(invalidSessionStrategy())
.maximumSessions(1)
.maxSessionsPreventsLogin(true)
.sessionRegistry(sessionRegistry())
.expiredSessionStrategy(sessionInformationExpiredStrategy())
return http.build();
}
...
@Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}
@Bean
public SessionInformationExpiredStrategy sessionInformationExpiredStrategy() {
return event -> {
HttpServletResponse response = event.getResponse();
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("""
{
"code": "SESSION_EXPIRED",
"message": "다른 곳에서 로그인되어 세션이 만료되었습니다."
}
""");
};
}
@Bean
public InvalidSessionStrategy invalidSessionStrategy() {
return new InvalidSessionStrategy() {
@Override
public void onInvalidSessionDetected(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().write("""
{
"code": "SESSION_EXPIRED",
"message": "만료된 세션입니다."
}
""");
}
};
}
}
SessionManagement 옵션 설명
- sessionCreationPolicy
- IF_REQUIRED : 기본값. 필요시 생성
- STATELESS : JWT 이용시 설정.
- NEVER : 사용치 않음
- ALWAYS : 항상 사용
- maxSessionPreventsLogin : 최대 세션 도달시 로그인 허용 여부
- false일 경우 기존 로그인 세션은 풀리고 새 로그인 세션 유지
- true일 경우 새 로그인이 안된다.
- maxSessions : 동시 최대 세션 수
- expiredSessionStrategy : 세션이 만료 되었을때 클라이언트에 응답하기 위한 부분
- invalidSessionStrategy : 세션이 없을경우, 틀릴경우 응답하기 위한 부분
세션의 타임아웃을 설정하기 위해 applicaion.yaml 에서 설정해 준다.
server:
servlet:
session:
timeout: 30m
세션은, 쿠키에 자동으로 추가되므로, 쿠키 관련 설정도 해주어야 한다. 이 페이지(https://dean83.tistory.com/378) 에서 쿠키를 수동으로 발급 했을 때 에는 각종 설정들을 코드로 할 수 있었으나, 세션의 경우 자동으로 쿠키를 쓰다보니, 설정을 applicaion.yaml 에 추가 해야 한다.
server:
servlet:
session:
cookie:
http-only: true
secure: true
same-site: none'Backend > SpringBoot' 카테고리의 다른 글
| [Spring Security] CORS 설정 (0) | 2025.12.16 |
|---|---|
| [Spring Security] CSRF 토큰 사용 (0) | 2025.12.16 |
| [Spring Security] MethodSecurity 및 커스텀 핸들러 (0) | 2025.12.16 |
| [Spring Security] JWT 사용시 Filter 구성 예 (0) | 2025.12.15 |
| [Spring Security] 쿠키 및 세션 (0) | 2025.12.12 |