인증, 권한 부여 및 일반적인 공격에 대한 보호를 제공하는 프레임워크
스프링 시큐리티는 principal - credential 패턴을 이용하여 인증한다.
스프링 시큐리티는 서블릿 필터를 기반으로 서블릿을 지원.
클라이언트가 어플리케이션으로 요청을 전송하면, 컨테이너는 Servlet과 여러 Filter로 구성된 FilterChain을 만든다. 그리고 요청 URI path 기반으로 HttpServletRequest를 처리한다.
Spring MVC 애플리케이션에서의 Servlet은 DispatcherServlet을 이용한다.

단일 HttpServletRequest, response 처리는 최대 한개의 Servlet이 담당하지만, Filter는 그림과 같이 여러개를 사용할 수 있다.
FilterChain 안에 있을 때 효력을 발휘한다.DelegatingfilterProxy라는 Filter 구현체로 서블릿 컨테이너의 생명주기와 스프링의 ApplicationContext를 연결한다.
서블릿 컨테이너는 Filter를 등록할 수 있지만, 스프링이 정의하는 빈은 인식하지 못한다. 하지만 DelegatingFilterProxy는 표준 서블릿 컨테이너 메커니즘으로 등록할 수 있으면서도, 모든 처리를 Filter를 구현한 스프링 빈으로 위임해준다.

DelegatingFilterProxy는 ApplicationContext에서 Bean Filter0을 찾아 실행한다.
FilterCHainProxy는 스프링 시큐리티가 제공하는 특별한 Filter로, SecurityFilterChain을 통해 여러 Filter 인스턴스로 위임한다.Bean이기 때문에 보통 DelegatingFilterProxy로 감싸져있다.

FilterChainProxy가 요청에 사용할 스프링 시큐리티의 필터들을 선택할 때는, SecurityFilterCHain을 사용한다.
FilterChainProxy는 스프링 시큐리티의 중심점이자 시작점이기 때문에, 필수로 여겨지는 작업을 수행할 수 있다.
예를 들어 SecurityContext를 비워 메모리 릭을 방지하거나, HttpFirewall을 적용하여 공격을 방어할 수도 있다.

이 이미지에는 여러개의 securityFilterCHain이 있는데, 어떤 체인을 사용할지는 FilterChainProxy가 결정하고, 가장 먼저 매칭한 SecurityFilterChain을 실행한다.
SecurityFIlterChain은 고유하고 격리된 설정을 가질 수 있다. 어플리케이션의 특정 요청은 시큐리티가 무시하길 바란다면, SecurityFilterChain에 보안 Filter를 0개 설정하는 것도 가능하다.
보안 필터들은 securityFilterChain API를 사용하여 FilterChainProxy에 삽입된다. 인증, 권한 부여, 악용 방지 등 다양한 목적으로 사용될 수 있는데, 필터는 특정 순서로 실행된다. 예를 들어 인증을 수행하는 필터는 권한 부여를 수행하는 필터보다 먼저 호출되어야 한다.
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(Customizer.withDefaults())
.authorizeHttpRequests(authorize -> authorize
.anyRequest().authenticated()
)
.httpBasic(Customizer.withDefaults())
.formLogin(Customizer.withDefaults());
return http.build();
}
}
위 구성의 순서는 다음과 같다.
ExceptionTranslationFilter는 AccessDeniedException을 해석하고 AuthenticationException을 HTTP응답으로 바꿔준다.

1. 먼저 ExceptionTranslationFilter는, FilterChain.doFilter를 호출해서 어플리케이션의 나머지 로직을 실행한다.
인증받지 않은 사용자거나 AuthenticationException이 발생한경우 인증을 시작한다.
2-1. securityContextHolder를 비우고
2-2. RequestCache에 HttpServletRequest를 저장한다. 사용자 인증에 성공하면 RequestCach로 기존 요청 처리를 이어간다.
2-3. AuthnticationEntryPoint는 클라이언트에 credential을 요청할 때 사용한다. 예를 들어 로그인 페이지로 리다이렉트하거나 인증헤더를 전송한다.
반대로 AccessDeniedException이라면 접근을 거부한다. 거절된 요청은 AccessDeniedHandler에서 처리한다.
애플리케이션이 AccessDeniedException 또는 AuthenticationException를 발생시키지 않으면 ExceptionTranslationFilter는 아무 작업도 수행하지 않는다.
try {
filterChain.doFilter(request, response);
} catch (AccessDeniedException | AuthenticationException ex) {
if (!authenticated || ex instanceof AuthenticationException) {
startAuthentication();
} else {
accessDenied();
}
}
출처: 스프링 시큐리티 공식 문서