[Spring Security] Spring Security Architecture

구범모·2023년 8월 2일
0

본 글에 앞서, Spring Security는 큰 관점에서 인증인가로 나뉜다.

💡 인증이란?

사용자의 신원을 검증하는 프로세스. (ex : 로그인)

💡 인가란?

인증 이후의 프로세스. 사용자마다 특정 리소스 혹은 기능에 접근할 수 있는 권한이 다르므로, 해당 권한을 부여(허락)하는 것을 뜻한다.

거시적인 관점에서, Spring Security는 웹 요청을 가로챈(intercept) 후, 사용자에게 인증 절차를 밟게 한 이후, 적절한 권한이 있는지 확인한다.

Authentication Manager

  • 사용자 인증 관련 처리 담당.

Access Decision Manager

  • 사용자 인가 관련 처리 담당.

https://docs.spring.io/spring-security/reference/servlet/architecture.html#servlet-filterchainproxy

Filter

  • 클라이언트가 요청을 보내면, 한 개 이상의 Filter 인스턴스와 Servlet을 포함하는 Container가 만들어 진다.
  • 해당 필터들을 다 거쳐야 Servlet에 도달 할 수 있다.
  • 필터들은 다양한 종류가 있으며, 각 필터마다 필터링 하는 기준이 있고 해당 기준에 부합하지 않으면 예외를 던진다.
  • 필터는 아래에 있는 필터 인스턴스 혹은 Servlet에 영향을 끼치기 때문에, 필터의 순서가 아주 중요하다.(공식문서에서도 이에 대해 언급했다.)
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException {
    Filter delegateToUse = this.delegate;
    if (delegateToUse == null) {
        synchronized(this.delegateMonitor) {
            delegateToUse = this.delegate;
            if (delegateToUse == null) {
                WebApplicationContext wac = this.findWebApplicationContext();
                if (wac == null) {
                    throw new IllegalStateException("No WebApplicationContext found: no ContextLoaderListener or DispatcherServlet registered?");
                }

                delegateToUse = this.initDelegate(wac);
            }

            this.delegate = delegateToUse;
        }
    }

    this.invokeDelegate(delegateToUse, request, response, filterChain);
}
  • 보통 다음 3개의 메소드가 있다.
    • init(FilterConfig config) — 필터를 시작할때 호출되는 메소드
    • doFilter(HttpServletRequest request,HttpServletResponse response, FilterChain chain) — 유저가 리소스에 요청을 보낼 때 실행된다. 필터링 작업을 실행한다.
    • destroy() — 필터의 작업을 끝마치고 호출된다.

DelegatingFilterProxy

  • Spring의 ApplicationContext와 Servlet 컨테이너의 생명주기를 이어주는 역할을 한다.
  • Servlet 컨테이너는 필터 인스턴스 등록을 허용하지만, Spring-defined bean들에 대해 알지 못하므로, DelegatingFilterProxy를 등록 이후에 이 클래스를 통해, Filter를 구현하는 Spring bean들에게 필터링을 위임한다.

FilterChainProxy

  • 웹 요청은 Servlet을 통해 들어오며, 들어온 요청은 위에서 볼 수 있듯이 filter들을 거친다.
  • 모든 필터를 거치긴 하지만, 모든 필터가 동작하지는 않는다.(각 필터에서 동작 여부를 결정하고, 동작하지 않는다면 다음 필터로 요청을 넘긴다.)
  • 요청을 처리한 이후 응답을 반환할 때는 거쳐왔던 필터를 역순으로 거쳐서 반환된다.
  • DelegatingFilterProxy의 구현체이다.
  • FilterChainProxy뿐만이 아닌, 다른 필터들도 다수 존재하지만, FilterChainProxy는 SecurityFitlerChain을 통해 다수의 Filter 객체로 처리를 위임한다.
  • Spring Security의 Servlet support가 FilterChainProxy로부터 시작하기에, Spring Security 관련 문제를 해결하려면 이 클래스에 디버깅 포인트를 찍고 시작하는 것이 좋다.

Security Filter

  • SecurityFilterChain API를 이용하여 FilterChainProxy에 등록된다.
  • 인증, 인가, exploit protection 등 다양한 목적으로 이용되는 필터들이 있다.
  • 실행되어야 하는 순서에 맞게 실행된다. (여기에 Spring Security Filter의 순서가 있다.)
@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();
    }

}

필터 실행 순서

FilterAdded by
CsrfFilterHttpSecurity#csrf
UsernamePasswordAuthenticationFilterHttpSecurity#formLogin
BasicAuthenticationFilterHttpSecurity#httpBasic
AuthorizationFilterHttpSecurity#authorizeHttpRequests

Config에서 등록 순서에 상관없이, 절대적인 Filter 순서에 따라 invoke된다.

profile
우상향 하는 개발자

0개의 댓글