SecurityPersistenceFilter

midas·2022년 5월 20일
1

🚪 SecurityPersistenceFilter란?

이 친구는 SecurityContext의 객체 생성, 저장, 조회를 담당합니다.
인증 관련 필터 중에 가장 최상단에 위치 → 이미 인증된 사용자는 다시 로그인할 필요가 없습니다.

⚡️ 공통적으로 마지막에는 SecurityContextHolder를 초기화합니다.

🚀 SecurityPersistenceFilter - doFilter()

private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
  if (request.getAttribute("__spring_security_scpf_applied") != null) {
    chain.doFilter(request, response);
  } else {
    request.setAttribute("__spring_security_scpf_applied", Boolean.TRUE);
    if (this.forceEagerSessionCreation) {
        HttpSession session = request.getSession();
        if (this.logger.isDebugEnabled() && session.isNew()) {
            this.logger.debug(LogMessage.format("Created session %s eagerly", session.getId()));
        }
    }

    HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
    // ✨ HttpSessionSecurityContextRepository - loadContext() 에서는 총 2가지 일을 합니다.
    // 1. Session → SecurityContext 정보를 가져옵니다.
    // 2-1. context != null 이라면 그대로 반환
    // 2-2. context == null → 새로운 context를 생성해서 반환하게 됩니다.
    SecurityContext contextBeforeChainExecution = this.repo.loadContext(holder);
    boolean var10 = false;

    try {
        var10 = true;
        // ✨ SecurityContextHolder에 SecurityContext를 등록합니다.
        SecurityContextHolder.setContext(contextBeforeChainExecution);
        if (contextBeforeChainExecution.getAuthentication() == null) {
            this.logger.debug("Set SecurityContextHolder to empty SecurityContext");
        } else if (this.logger.isDebugEnabled()) {
            this.logger.debug(LogMessage.format("Set SecurityContextHolder to %s", contextBeforeChainExecution));
        }

		// ✨ 다음 필터로 넘어가게 됩니다.
		// 로그인 하지 않은 상태라면 AnonymousAuthenticationFilter로 넘어가겠네요. 👀
        chain.doFilter(holder.getRequest(), holder.getResponse());
        var10 = false;
    } finally {
        if (var10) {
            SecurityContext contextAfterChainExecution = SecurityContextHolder.getContext();
            SecurityContextHolder.clearContext();
            this.repo.saveContext(contextAfterChainExecution, holder.getRequest(), holder.getResponse());
            request.removeAttribute("__spring_security_scpf_applied");
            this.logger.debug("Cleared SecurityContextHolder to complete request");
        }
    }

    SecurityContext contextAfterChainExecution = SecurityContextHolder.getContext();

	// ✨ 최종 응답에서는 무조건 SecurityContextHolder를 초기화 하게 되구요.
    SecurityContextHolder.clearContext();

	// ✨ 세션에 SecurityContext 정보를 저장하게 됩니다.
    this.repo.saveContext(contextAfterChainExecution, holder.getRequest(), holder.getResponse());
    request.removeAttribute("__spring_security_scpf_applied");
    this.logger.debug("Cleared SecurityContextHolder to complete request");
  }
}
profile
BackEnd 개발 일기

1개의 댓글

comment-user-thumbnail
2023년 12월 6일

포스팅 잘 보면서 세션관련된 filter 로직 학습 잘 하고 있습니다! 혹시 이번포스팅이랑 다음포스팅에서 최종으로 완성한 소스코드 공유해주실 수 있나요??

답글 달기