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개의 추가 메서드를 사용할 수 있게 해줌.