Spring Security - 17. SecurityContextHolderAwareRequestFilter.

하쮸·2025년 3월 10일

1. SecurityContextHolderAwareRequestFilter

  • SecurityContextHolderAwareRequestFilter는 스프링 시큐리티 의존성을 추가하면 자동으로 등록되는 시큐리티 필터체인에 소속되어 있는 필터 중 하나임
    • 이 필터는 Servlet API 보안(Sucurity) 메서드구현하는 요청 래퍼ServletRequest추가해주는 필터
      • HttpServletRequest.authenticate(HttpServletResponse)
        • 사용자가 인증되었는지 확인하고, 인증되지 않은 경우 로그인 페이지로 보냄.
      • HttpServletRequest.login(String, String)
        • AuthenticationManager를 사용하여 사용자가 직접 인증할 수 있도록 함.
      • HttpServletRequest.logout()
        • Spring Security에서 설정된 LogoutHandlers를 사용하여 사용자가 로그아웃할 수 있도록 함.
      • AsyncContext.start(Runnable)
        • SecurityContextHolder의 SecurityContext를 Runnable을 처리하는 스레드로 자동으로 복사.
  • 사용자가 직접 커스텀 시큐리티필터체인을 등록하더라도 기본적으로 등록됨.
public class SecurityContextHolderAwareRequestFilter extends GenericFilterBean {

	private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
		.getContextHolderStrategy();

	private String rolePrefix = "ROLE_";

	private HttpServletRequestFactory requestFactory;

	private AuthenticationEntryPoint authenticationEntryPoint;

	private AuthenticationManager authenticationManager;

	private List<LogoutHandler> logoutHandlers;

	private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();

	private SecurityContextRepository securityContextRepository = new HttpSessionSecurityContextRepository();


	public void setSecurityContextRepository(SecurityContextRepository securityContextRepository) {
		Assert.notNull(securityContextRepository, "securityContextRepository cannot be null");
		this.securityContextRepository = securityContextRepository;
	}


	public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
		Assert.notNull(securityContextHolderStrategy, "securityContextHolderStrategy cannot be null");
		this.securityContextHolderStrategy = securityContextHolderStrategy;
	}

	public void setRolePrefix(String rolePrefix) {
		Assert.notNull(rolePrefix, "Role prefix must not be null");
		this.rolePrefix = rolePrefix;
		updateFactory();
	}


	public void setAuthenticationEntryPoint(AuthenticationEntryPoint authenticationEntryPoint) {
		this.authenticationEntryPoint = authenticationEntryPoint;
	}


	public void setAuthenticationManager(AuthenticationManager authenticationManager) {
		this.authenticationManager = authenticationManager;
	}


	public void setLogoutHandlers(List<LogoutHandler> logoutHandlers) {
		this.logoutHandlers = logoutHandlers;
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
			throws IOException, ServletException {
		chain.doFilter(this.requestFactory.create((HttpServletRequest) req, (HttpServletResponse) res), res);
	}

	@Override
	public void afterPropertiesSet() throws ServletException {
		super.afterPropertiesSet();
		updateFactory();
	}

	private void updateFactory() {
		String rolePrefix = this.rolePrefix;
		this.requestFactory = createServlet3Factory(rolePrefix);
	}


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

	private HttpServletRequestFactory createServlet3Factory(String rolePrefix) {
		HttpServlet3RequestFactory factory = new HttpServlet3RequestFactory(rolePrefix, this.securityContextRepository);
		factory.setTrustResolver(this.trustResolver);
		factory.setAuthenticationEntryPoint(this.authenticationEntryPoint);
		factory.setAuthenticationManager(this.authenticationManager);
		factory.setLogoutHandlers(this.logoutHandlers);
		factory.setSecurityContextHolderStrategy(this.securityContextHolderStrategy);
		return factory;
	}

}
  • doFilter()
    • 요청(req)SecurityContextHolderAwareRequestWrapper로 감싸서 위에서 말한 4개의 추가 메서드를 사용할 수 있게 해줌.
profile
Every cloud has a silver lining.

0개의 댓글