Spring

세션관리

yoon9 2022. 11. 15. 21:19

스프링시큐리티로 개발 및 공부중에 중복로그인에 대해서 알아보았습니다.

ConcurrentSessionFilter가 존재하는데

private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpSession session = request.getSession(false);
    if (session != null) {
        SessionInformation info = this.sessionRegistry.getSessionInformation(session.getId());
        if (info != null) {
            if (info.isExpired()) {
                this.logger.debug(LogMessage.of(() -> {
                    return "Requested session ID " + request.getRequestedSessionId() + " has expired.";
                }));
                this.doLogout(request, response);
                this.sessionInformationExpiredStrategy.onExpiredSessionDetected(new SessionInformationExpiredEvent(info, request, response));
                return;
            }

            this.sessionRegistry.refreshLastRequest(info.getSessionId());
        }
    }

    chain.doFilter(request, response);
}

이 필터는 request오는 것에 세션을 찾아보고 거기서 만료가 되었는지 아닌지 확인을 하여서 만료를 할지 아니면 그냥 넘어가는지 확인을 해주는 필터이다 여기서 중요한것이 sessionRegistry 이다 .

sessionRegistry가 세션에 대해 만료나 관리를 해준다 이것을 구현을 한 것이SessionRegistryImpl이다.

그래서 보면 ConcurrentSessionFilter는 request마다 expire가 찍혀있는지 없는지 확인을 하고 찍혀있으면

만료를 해주는 작업을 해준다.

그럼 어떠한 경우에는 expire를 찍어줄지가 관건이다.

sessionManagementFilter에서 할 수 있다.

public class SessionManagementFilter extends GenericFilterBean {
    static final String FILTER_APPLIED = "__spring_security_session_mgmt_filter_applied";
    private final SecurityContextRepository securityContextRepository;
    private SessionAuthenticationStrategy sessionAuthenticationStrategy;
    private AuthenticationTrustResolver trustResolver;
    private InvalidSessionStrategy invalidSessionStrategy;
    private AuthenticationFailureHandler failureHandler;

    public SessionManagementFilter(SecurityContextRepository securityContextRepository) {
        this(securityContextRepository, new SessionFixationProtectionStrategy());
    }

    public SessionManagementFilter(SecurityContextRepository securityContextRepository, SessionAuthenticationStrategy sessionStrategy) {
        this.trustResolver = new AuthenticationTrustResolverImpl();
        this.invalidSessionStrategy = null;
        this.failureHandler = new SimpleUrlAuthenticationFailureHandler();
        Assert.notNull(securityContextRepository, "SecurityContextRepository cannot be null");
        Assert.notNull(sessionStrategy, "SessionAuthenticationStrategy cannot be null");
        this.securityContextRepository = securityContextRepository;
        this.sessionAuthenticationStrategy = sessionStrategy;
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        this.doFilter((HttpServletRequest)request, (HttpServletResponse)response, chain);
    }

    private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        if (request.getAttribute("__spring_security_session_mgmt_filter_applied") != null) {
            chain.doFilter(request, response);
        } else {
            request.setAttribute("__spring_security_session_mgmt_filter_applied", Boolean.TRUE);
            if (!this.securityContextRepository.containsContext(request)) {
                Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
                if (authentication != null && !this.trustResolver.isAnonymous(authentication)) {
                    try {
                        this.sessionAuthenticationStrategy.onAuthentication(authentication, request, response);
                    } catch (SessionAuthenticationException var6) {
                        this.logger.debug("SessionAuthenticationStrategy rejected the authentication object", var6);
                        SecurityContextHolder.clearContext();
                        this.failureHandler.onAuthenticationFailure(request, response, var6);
                        return;
                    }

                    this.securityContextRepository.saveContext(SecurityContextHolder.getContext(), request, response);
                } else if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) {
                    if (this.logger.isDebugEnabled()) {
                        this.logger.debug(LogMessage.format("Request requested invalid session id %s", request.getRequestedSessionId()));
                    }

                    if (this.invalidSessionStrategy != null) {
                        this.invalidSessionStrategy.onInvalidSessionDetected(request, response);
                        return;
                    }
                }
            }

            chain.doFilter(request, response);
        }
    }

    public void setInvalidSessionStrategy(InvalidSessionStrategy invalidSessionStrategy) {
        this.invalidSessionStrategy = invalidSessionStrategy;
    }

    public void setAuthenticationFailureHandler(AuthenticationFailureHandler failureHandler) {
        Assert.notNull(failureHandler, "failureHandler cannot be null");
        this.failureHandler = failureHandler;
    }

    public void setTrustResolver(AuthenticationTrustResolver trustResolver) {
        Assert.notNull(trustResolver, "trustResolver cannot be null");
        this.trustResolver = trustResolver;
    }
}