데브코스 W11D2

코끼릭·2022년 6월 1일
0

TIL

목록 보기
34/36

Session

HTTP 프로토콜의 특징인 Connectionless와 Stateless를 보완하기 위한 목적으로 클라이언트의 정보 유지를 하기 위해 서버에서 사용하는 것이다. (쿠키의 경우 클라이언트에서 HTTP를 보완하기 위해 사용된다.)

  1. 인증된 사용자 정보를 저장하기 위해 서버에서 session을 만들고 식별자인 session-id를 클라이언트에 응답한다.

  2. 클라이언트(웹브라우저)는 session-id를 쿠키에 저장한다.

  3. 클라이언트는 다음 요청에서는 쿠키에 저장된 session-id를 포함시켜 서버가 클라이언트를 식별할 수 있게 한다.

  4. 서버가 식별된 클라이언트가 요청한 응답을 보낸다.

Session Cluster


3-Tier Architecture에서 서비스 이용자가 많을 때는 어플리케이션 계층을 Scale-out을 하고 서비스의 앞단에 로드 밸런서를 배치하여 트래픽을 분산시키게 되는데 만약 하나의 서버의 장애가 발생하게 되면 해당 서버에서 생성한 Session을 활용한 인증이 무효화 되기 때문에 사용자는 다시 인증을 해야되는 단점을 가지고 있다. 이러한 취약점을 개선하고자 Session을 서버 메모리가 아닌 별도의 외부 스토리지에 저장한다는 Session Cluster 개념이 도입되었다.

Spring Session

Spring Boot 웹 어플리케이션에서 Session Cluster를 구현하는데 다양한 기능을 제공한다.

  • SessionRepository
    Session의 생성과 저장, 조회, 삭제 처리를 담당하고 구현체로는 MapSessionRepository, RedisIndexedSessionRepository, JdbcIndexedSessionRepository가 있다.

    public interface SessionRepository<S extends Session> {
    
        S createSession();
    
        void save(S session);
    
        S findById(String id);
    
        void deleteById(String id);
    
    }

DelegatingFilterProxy

사용자의 요청 처리를 Spring Security의 FilterChainProxy로 위임하기 위해 동작하는 서블릿 필터이다.

SessionRepositoryFilter

스프링 시큐리티의 필터체인 프록시가 수행되기 전 처리되는 필터로 HttpServletRequest, HttpServletResponse 인터페이스 구현을 SessionRepositoryRequestWrapper, SessionRepositoryResponseWrapper 구현체로 교체하는 역할을 수행한다.

SecurityContextPersistenceFilter

SecurityContextRepository 인터페이스 구현체인 HttpSessionSecurityContextRepository 클래스를 이용하여 요청과 응답, 세션정보를 가져오고 사용자의 SecurityContext를 생성, 갱신하는 역할을 담당한다.

@Override
public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder) {
	HttpServletRequest request = requestResponseHolder.getRequest();
	HttpServletResponse response = requestResponseHolder.getResponse();
	HttpSession httpSession = request.getSession(false);
	SecurityContext context = readSecurityContextFromSession(httpSession);
	if (context == null) {
		context = generateNewContext();
		if (this.logger.isTraceEnabled()) {
			this.logger.trace(LogMessage.format("Created %s", context));
		}
	}
	SaveToSessionResponseWrapper wrappedResponse = new SaveToSessionResponseWrapper(response, request,
			httpSession != null, context);
	requestResponseHolder.setResponse(wrappedResponse);
	requestResponseHolder.setRequest(new SaveToSessionRequestWrapper(request, wrappedResponse));
	return context;
}
profile
ㅇㅅㅇ

0개의 댓글