[Spring Security] 기본 동작 원리

2023. 3. 6. 22:26Spring/Security

1. 스프링 시큐리티란?

스프링 시큐리티는 스프링 생태계에서 지원하는 보안 관련 기능을 제공하는 프레임워크이다. 기본적으로 스프링을 백엔드로 활용한다면 보안과 관련된 부분은 서블릿 필터나 스프링 인터셉터에서 처리했다. 하지만 일일이 이런 식으로 실제 프로젝트에서 하는 것은 체계화되지 않은 부분에 불과했고 이를 스프링에서 공식적으로 제공하였다.

본격적으로 시작하기 전에 보안 용어들을 정리하고 가도록 하겠다.

  • 인증(Authentication): 요청한 사람이 본인인지를 확인하는 절차
  • 인가(Authorization): 인증된 사용자가 접근한 자원에 권한이 있는지를 확인하는 절차

2. 기본 동작 원리 및 흐름

스프링 시큐리티는 서블릿 필터 기반으로 동작하면서 스프링의 많은 지원을 함께 사용할 수 있도록 했다. 서블릿과 스프링의 컨텍스트는 다르다. 서블릿은 톰캣과 같은 WAS 단에서 동작하며 모든 웹 요청을 먼저 처리한다. 앞선 필터의 과정을 모두 거치고 난 다음에야 요청은 스프링 컨텍스트로 넘어온다. 다시 말하면, 필터에서는 스프링의 기능을 사용할 수 없다는 말이다. 그렇다면 필터에서도 스프링 기능을 사용하는 방법을 어떻게 만들어냈을까? 바로 위임(delegation)으로 이 마법을 만들어냈다.

스프링 시큐리티는 프로그램이 실행될 때 하나의 필터를 추가한다. 이 필터는 DelegatingFilterProxy이다. 그리고 이 필터는 웹 요청을 받으면 내부에서 스프링 컨텍스트 내의 로직으로 요청을 위임한다. 이 필터에서는 내부에 필터를 구현한 빈이 등록되어 있고 이 빈이 요청을 처리한다.

이렇게 위임을 받는 필터가 FilterChainProxy이다. 이 객체 안에는 SecurityFilterChain 타입의 리스트가 들어있다. SecurityFilterChain은 인터페이스며, 이름 그대로 보안과 관련된 여러 필터들로 구성된 체인을 의미한다. 코드를 살펴보면 다음과 같다.

public interface SecurityFilterChain {

	boolean matches(HttpServletRequest request);

	List<Filter> getFilters();

}

SecurityFilterChain의 구현체는 matches()를 통해 자신에게 온 요청인지 확인하고 매칭된다면 getFilters()를 통해 FilterChainProxy에게 필터 체인을 제공한다. 다시 말하면 여러 개의 필터 체인을 가지고 있을 수 있으며 요청에 따라 다른 보안 로직을 처리할 수 있다는 뜻이다. 그림으로 보면 다음과 같다.

이러한 설정을 스프링 부트에서는 @EnableWebSecurity 라는 어노테이션을 등록함으로써 간편하게 사용할 수 있다.

이 어노테이션을 적용하면 내부에서 @EnableAuthoConfiguration 어노테이션이 동작하면서 SecurityFilterAutoConfiguration 클래스를 로드하고 FilterChainProxy 클래스인 springSecurityFilterChain이라는 빈을 등록해준다. 그래서 이후 DelegatingFilterProxy가 필터로 동작하면서 springSecurityFilterChain에게 위임한다.

 

springSecurityFilterChain이라는 이름으로 빈을 등록한다.
DelegatingFilterProxy의 initDelegate가 실행될 때 springSecurityFilterChain 이라는 빈을 찾고 있는 것을 볼 수 있다.
그리고 실제로 들어온 빈의 타입은 FilterChainProxy인 것을 확인할 수 있다.

실제 WebSecurity 클래스에서 보면 FilterChainProxy를 생성할 때 securityFilterChain을 인수로 받는 것을 볼 수 있다.

 

이렇게 모든 필터를 순회하면서 인증 및 인가 처리를 한다. 그리고 마지막 필터까지 예외가 발생하지 않으면 나머지 필터를 건너다 결국 스프링의 DispatcherServlet으로 넘어가고 비즈니스 로직을 만나게 된다.

아래서 두 번째 사진의 FilterChainProxy를 자세히 보면 Filter Chains에 DefaultSecurityFilterChain이라고 하는 필터 체인이 들어 있는 것을 볼 수 있다. 스프링 시큐리티가 기본적으로 제공해주는 필터 체인이 저것이다.

마치며

스프링 시큐리티가 필터 환경에서 스프링 기능을 적용하도록 만든 전체적인 구조와 흐름을 살펴보았다. 복잡하지만 꼭 이해해야 하는 부분이므로 직접 중단점도 찍어보고 반복하면서 이해하는 것이 좋다.