1. 사용자가 보호된 리소스 요청
2. 인증 관리자가 사용자 크리덴셜 요청
3. 사용자가 인증 관리자에게 크리덴셜 제공
4. 인증 관리자가 크리덴셜 저장소에서 사용자의 크리덴셜 조회
5. 인증 관리자는 사용자가 제공한 크리덴셜과 크리덴셜 저장소에 저장된 크리덴셜을 비교해 검증
6. 유효한 크리덴셜이 아닌 경우 예외 throw
7. 유효한 크리덴셜일 경우 접근 결정 관리자가 용자가 적절한 권한을 부여받았는지 검증
8. 적절한 권한을 부여받지 못한 사용자일 경우 예외 throw
9. 적절한 권한을 부여받은 사용자일 경우 리소스 접근 허용
사용자의 웹 요청이 Controller 같은 엔드포인트를 거쳐 접근하려는 리소스에 도달하기 전 인증 관리자나 접근 결정 관리자 같은 컴포넌트가 중간에 웹 요청을 가로채 사용자의 크리덴셜과 접근 권한을 검증
서블릿 필터가 애플리케이션의 엔드포인트에 요청이 도달하기 전에 중간에서 요청을 가로챈 후 어떤 처리를 할 수 있는 적절한 포인트를 제공
javax.servlet.Filter 인터페이스를 구현한 서블릿 필터는 웹 요청(request)을 가로채어 전처리를 할 수 있으며,
엔드포인트에서 요청 처리가 끝난 후 전달되는 응답(reponse)을 클라이언트에게 전달하기 전에 후처리 가능
서블릿 필터는 하나 이상의 필터들을 연결해 필터 체인(Filter Chain)을 구성 가능
서블릿 필터는 각각의 필터들이 doFilter()라는 메서드를 구현해야 하며, doFilter() 메서드 호출을 통해 필터 체인을 형성
서블릿 필터에서 작업을 수행한 뒤, HttpServlet을 거쳐 DispatcherServlet에 요청이 전달되며,
반대로 DispatcherServlet에서 전달한 응답에 대해 작업 수행 가능
@Order(1) // (1)
public class FirstFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
System.out.println("# First Filter init");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("# First Filter doFilter 시작");
chain.doFilter(request, response);
System.out.println("# First Filter doFilter 종료");
}
@Override
public void destroy() {
Filter.super.destroy();
System.out.println("# First Filter destroy");
}
}
@Order(2)
public class SecondFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
Filter.super.init(filterConfig);
System.out.println("# Second Filter init");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("# Second Filter doFilter 시작");
chain.doFilter(request, response);
System.out.println("# Second Filter doFilter 종료");
}
@Override
public void destroy() {
Filter.super.destroy();
System.out.println("# Second Filter destroy");
}
}
@Configuration
public class FilterConfiguration {
@Bean
public FilterRegistrationBean<FirstFilter> firstFilterRegister() {
FilterRegistrationBean<FirstFilter> registrationBean = new FilterRegistrationBean<>(new FirstFilter());
// registrationBean.setOrder(1); // (1)
return registrationBean;
}
@Bean
public FilterRegistrationBean<SecondFilter> secondFilterRegister() {
FilterRegistrationBean<SecondFilter> registrationBean = new FilterRegistrationBean<>(new SecondFilter());
// registrationBean.setOrder(2);
return registrationBean;
}
}
# Second Filter init
# First Filter init
# First Filter doFilter 시작
# Second Filter doFilter 시작
# Second Filter doFilter 종료
# First Filter doFilter 종료
Filter 순서 지정 시 init() 메서드와 destroy() 메서드는 영향을 받지 않는다.
SecurityContext는 이후에 Spring Security의 세션 정책에 따라서 HttpSession에 저장되어 사용자의 인증 상태를 유지하기도 하고, HttpSession을 생성하지 않고 무상태를 유지하기도 함