본문 바로가기

Spring Boot/Security 쿠키,세션 기반 인증,인가

세션 관리 핵심 컴포넌트 : 세션 이벤트와 리스너

 - 세션의 생성, 소멸, 만료 이벤트의 동작 원리

 - 세션 이벤트를 감지하기 위해 리스너를 등록하는 방법

 - HttpSessionListener 와 Spring의 ApplicationListener 의 차이점

 - 직접 세션 이벤트를 로그로 확인해보기

 - 실무에서 세션 이벤트와 리스너를 어떻게 활용하는가


세션 이벤트와 리스너 개요

1. 개념

세션 이벤트(Session Event) 는 세션의 생성, 소멸, 만료 시점에 발생하는 이벤트임

리스너(Listener) 는 이러한 이벤트를 감지하고 특정 동작(로그 남기기, 리소스 정리 등) 을 수행할 수 있도록 돕는 컴포넌트임

 

사용자 - 서버 - 리스너로 이어지는 세션 이벤트 생성 - 소멸 과정


HttpSessionListener 활용

1. HttpSessionListener 개념

  • Java EE 표준 인터페이스
  • sessionCreated, SessionDestroyed 메서드를 통해 세션의 생성 / 소멸을 감지한다
import jakarta.servlet.http.HttpSessionEvent;
import jakarta.servlet.http.HttpSessionListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class CustomHttpSessionListener implements HttpSessionListener {
    private static final Logger log = LoggerFactory.getLogger(CustomHttpSessionListener.class);

    // 세션의 생성
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        log.info("[세션 생성] sessionId = {} 생성됨", se.getSession().getId());
    }

    // 세션의 소멸
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        log.info("[세션 소멸] sessionId = {} 소멸됨", se.getSession().getId());
    }
}

 

 

등록하는 방법 (web.xml 또는 Spring Boot)

import com.b1uffer.cookieandsession.Listener.CustomHttpSessionListener;
import jakarta.servlet.http.HttpSessionListener;
import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ListenerConfig {
    @Bean
    public ServletListenerRegistrationBean<HttpSessionListener> httpSessionListener() {
        return new ServletListenerRegistrationBean<>(new CustomHttpSessionListener());
    }
}

 


Spring ApplicationListener 활용하기

1. Spring 이벤트 시스템 연계

  • Spring 은 세션 관련 이벤트를 ApplicationEvent 로도 발행한다
  • ApplicationListener 를 구현하거나, @EventListener 를 통해 간단하게 감지할 수 있다고 함
  • HttpSessionCreatedEvent, HttpSessionDestroyedEvent 클래스를 통해 감지할 수 있다

 

 

2. 예제

SessionDestroyedEventListener.java

import org.springframework.context.ApplicationListener;
import org.springframework.security.web.session.HttpSessionDestroyedEvent;
import org.springframework.stereotype.Component;

/**
 * SecuritySessionEventListener 랑 둘중에 선택해서 사용하면 됨
 */
@Component
public class SessionDestroyedEventListener implements ApplicationListener<HttpSessionDestroyedEvent> {
    @Override
    public void onApplicationEvent(HttpSessionDestroyedEvent event) {
        event.getSecurityContexts().forEach(content -> {
            String username = content.getAuthentication().getName();
            System.out.println("[세션 만료 감지] 사용자 : " + username);
        });
    }
}

 

얘는 SessionDestroyedEvent의 구현체인 HttpSession 전용 이벤트를 받고 있다

 

 

SecuritySessionEventListener.java

import org.springframework.context.event.EventListener;
import org.springframework.security.core.session.SessionDestroyedEvent;
import org.springframework.stereotype.Component;

/**
 * SessionDestroyedEventListener 랑 둘중에 선택해서 사용하면 됨
 */
@Component
public class SecuritySessionEventListener {

    @EventListener
    public void handleSessionDestroyed(SessionDestroyedEvent event) {
        event.getSecurityContexts().forEach(context -> {
            System.out.println("[세션 만료] 사용자 : " + context.getAuthentication().getName());
        });
    }
}

 

얘는 Spring Security의 상위 추상 이벤트인 SessionDestroyedEvent 를 받는다

 

SessionDestroyedEvent 가 HttpSessionDestroyedEvent 의 부모이다.

둘 다 세션 종료를 감지할 수 있음

 

둘 중 하나를 선택해서 사용하면 된다

실무적으로는 Spring MVC / Security 세션 만료에 대해 감지한다면 SessionDestroyedEvent 를 사용한다곤 하는데
구체적으로 보고 싶다면 HttpSessionDestroyedEvent 를 써도 될 것 같다

 

둘 다 Component로 등록하면 둘 다 반응해서 로그가 두 번 뜰 수 있다

 

SecurityContext 까지 함께 확인할 수 있어서 사용자 단위 세션 추적에 적합하다고 함


세션 만료 감지

1. 타임아웃 기반 만료

application.yml 에서 세션 타임아웃을 설정할 수 있다

server:
  servlet:
    session:
      timeout: 30m

 

 

2. ConcurrentSessionFilter 기반 만료

  • ConcurrentSessionFilter 는 동시 세션 제어와 함께 사용되며, 만료된 세션을 감지하고 처리한다
  • 세션이 만료되면 HttpDestroyedEvent 가 발생하며, 리스너에서 이를 받아 처리할 수 있다

 

(1) 예제

import org.springframework.context.event.EventListener;
import org.springframework.security.web.session.HttpSessionDestroyedEvent;
import org.springframework.stereotype.Component;

@Component
public class ConcurrentSessionListener {
    @EventListener
    public void onSessionDestroyed(HttpSessionDestroyedEvent event) {
        String sessionId = event.getSession().getId();
        System.out.println("[ConcurrentSessionFilter] 세션 만료 감지 - ID : " + sessionId);
        event.getSecurityContexts().forEach(context -> {
            System.out.println("만료된 사용자 : " + context.getAuthentication().getName());
        });
    }
}

 

위 코드에서는 ConcurrentSessionFilter 가 만료된 세션을 감지하여 HttpSessionDestroyedEvent 를 발생시키고,

리스너에서 이를 로그로 기록한다

 


  • 로그 감사(Audit) : 보안상 중요한 서비스에서는 세션 생성 / 소멸을 모두 감사 로그에 기록한다
  • 리소스 정리 : 세션 만료시 DB 커넥션, 캐시 자원 등을 해제하는 작업에 활용할 수 있다
  • 보안 알림 : 특정 사용자 세션이 강제로 만료될 경우 알림을 발송하는 기능과 연계할 수 있다
  •  

정리

주제 핵심 포인트
HttpSessionListener 세션 생성 / 소멸 이벤트 감지 (Java EE 표준 서블릿)
ApplicationListener Spring 이벤트로 세션 종료 감지, 사용자 정보와 함께 확인 가능함
세션 만료 타임아웃 또는 동시 세션 제어에 의해 발생함
활용 사례 감사 로그, 리소스 정리, 보안 알림