이 친구는 SecurityContext의 객체 생성, 저장, 조회를 담당합니다.
인증 관련 필터 중에 가장 최상단에 위치 → 이미 인증된 사용자는 다시 로그인할 필요가 없습니다.
⚡️ 공통적으로 마지막에는 SecurityContextHolder를 초기화합니다.
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");
}
}
포스팅 잘 보면서 세션관련된 filter 로직 학습 잘 하고 있습니다! 혹시 이번포스팅이랑 다음포스팅에서 최종으로 완성한 소스코드 공유해주실 수 있나요??