프레임워크(Framework)/Spring

[Spring Security] 스프링 시큐리티의 구조와 흐름

잇트루 2022. 12. 26. 23:50
반응형

Intro

Spring Security를 구현한 코드의 흐름은 잘 드러나지는 않지만 내부적으로는 Spring Security에서 제공하는 컴포넌트들이 애플리케이션 내부에서 User의 인증과 인가(권한 부여)에 대한 처리를 알아서 해준다.

이처럼 내부에서 일어나는 과정들을 구체적으로 이해하지 못한 상태에서는 Spring Security라는 기술을 이해하는 데 있어 한계에 부딪힐 수 있다.

 

Spring Security를 애플리케이션에 적용하는데 어려움을 겪는 가장 큰 이유 중 하나는 Spring Security의 아키텍처(구조)와 Spring Security의 컴포넌트들이 어떻게 인터랙션해서 인증, 권한 등의 보안 작업을 처리하는지 이해하지 못했기 때문이다.

 

Spring Security의 동작 방식을 이해하기 위해서는 보호된 웹 요청을 처리하는 일반적인 처리 흐름과 Spring Security에서 지원하는 Filter의 역할을 이해하는 것이 선행되어야 한다.

 

 

보안이 적용된 웹 요청의 처리 흐름

Spring Security를 사용하지 않고 보안이 적용된 웹 요청의 처리 흐름은 다음과 같다.

  1. 리소스 요청 : 사용자가 보호된 리소스를 요청한다.
  2. 크리덴셜 요청 : 인증 관리자는 크리덴셜을 사용자에게 요청한다.
    • 크리덴셜(Credential) : 사용자를 증명하기 위한 구체적인 수단(로그인을 하기 위한 패스워드)
  3. 크리덴셜 제공 : 사용자는 인증 관리자의 요청을 받아 크리덴셜을 제공한다.
  4. 크리덴셜 조회 : 인증 관리자는 크리덴셜 저장소에서 사용자로부터 받은 크리덴셜을 조회한다.
  5. 크리덴셜 검증 : 인증 관리자는 사용자가 제공한 크리덴셜과 크리덴셜과 크리덴셜 저장소에 저장된 크리덴셜을 비교하여 검증한다.
  6. 유효한 크리덴셜이 아닌 경우 Exception을 던진다.
  7. 유효한 크리덴셜이면 다음 작업으로 처리한다.
  8. 접근 결정 관리자 역할을 하는 컴포넌트는 사용자가 적절한 권한을 부여받았는지 검증한다.
  9. 적절한 권한을 부여받지 못한 경우 Exception을 던진다.
  10. 적절한 권한을 부여받은 사용자이면 보호된 리소스의 접근을 허용한다.

 

 

웹 요청에서의 서블릿 필터와 필터 체인

서블릿 필터

위에서 설명한 보안이 적용된 웹 요청 처리 흐름을 보면, 사용자의 웹 요청이 Controller 같은 엔드포인트를 거쳐 접근하려는 리소스에 도달하기 전에 사용자의 크리덴셜과 접근 권한을 검증하는 것을 알 수 있다.

이는 인증 관리자나 접근 결정 관리자와 같은 컴포넌트들이 사용자의 웹 요청을 중간에 가로채 특정 처리를 했기 때문에 가능한 것이다.

 

서블릿 필터(Servlet Filter)는 서블릿 기반의 애플리케이션에서 사용자의 요청이 엔드포인트에 도달하기 전에 중간에 가로채서 어떤 처리를 할 수 있는 적절한 포인트를 제공한다.

 

서블릿 필터는 자바에서 제공하는 API로 javax.servlet 패키지에 인터페이스 형태로 정의되어 있다.

이를 구현한 서블릿 필터는 다음과 같은 역할을 할 수 있다.

  • 웹 요청(request) 시 엔드포인트에 도달하기 전에 전처리를 할 수 있다.
  • 웹 응답(response) 시 엔드포인트가 끝난 후 사용자에게 응답하기 전에 후처리를 할 수 있다.

 

필터 체인(Filter Chain)

서블릿 필터는 하나 이상의 필터들을 연결하여 필터 체인(Filter Chain)을 구성할 수 있다.

다음은 스프링 프레임워크의 DispatcherServlet에 클라이언트의 요청이 전달되기 전에 필터 체인을 구성한 예시이다.

  • 서블릿 필터는 각각의 필터들이 doFilter()라는 메서드를 구현해야 한다.
  • doFilter() 메서드 호출을 통해 필터 체인을 형성할 수 있다.
  • 클라이언트가 서버로 요청하면, doFilter() 메서드들을 거쳐 특정 작업을 수행한 뒤, HttpServlet을 거쳐 DispatcherServlet에 요청이 전달된다.
  • 반대로 DispatcherServlet가 보내는 응답 또한 클라이언트에게 도달하기 전에 doFilter() 메서드들을 거쳐 특정 작업을 수행할 수 있다.

 

 

Spring Security에서의 필터 역할

서블릿 필터는 클라이언트의 요청이나 서버의 응답 중간에 추가적인 작업을 할 수 있다.

Spring Security에서의 필터 또한 서블릿 필터와 같이 중간에 요청을 가로챈 뒤, 보안과 관련된 추가적인 작업을 하는 것이다.

 

다음 이미지는 서블릿 필터에 Spring Security Filter가 추가된 모습이다.

  • 서블릿 필터 사이에 Spring Security Filter 영역이 생긴 것을 볼 수 있다.
  • DelegatingFilterProxy와 FilterChainProxy는 Filter 인터페이스를 구현한 구현체이다.
  • 따라서 Spring Security Filter는 서블릿 필터와 역할에 대해서는 큰 차이가 없다.

 

 

스프링 시큐리티 필터와 서블릿 필터의 차이

가장 큰 차이는 스프링 시큐리티 필터는 스프링 컨테이너의 관리를 받는다는 것이다.

따라서 스프링 시큐리티 필터는 의존관계 주입(DI)을 통해 사용할 수 있다.

 

서블릿 필터와 연결되는 스프링 시큐리티 필터를 ApplicationContext에 빈(Bean)으로 등록한 후에 등록된 빈들을 이용하여 보안과 관련된 여러 가지 작업을 처리하게 된다.

 

 

DelegatingFilterProxy와 FilterChainProxy

DelegatingFilterProxy

DelegatingFilterProxy는 보안과 관련된 어떤 작업을 처리하는 것이 아닌, 서블릿 컨테이너 영역의 필터와 스프링 컨테이너에 빈으로 등록된 필터를 연결해주는 브릿지 역할을 한다.

 

FilterChainProxy

위 이미지를 살펴보면, FilterChainProxy에서 가리키는 곳을 보면, Spring Security Filter Chain을 향하는 것을 알 수 있다. FilterChainProxy는 필터 체인을 사용하기 위한 진입점이다.

 

스프링 시큐리티의 필터 체인(Filter Chain)은 스프링 시큐리티에서 보안을 위한 작업을 처리하는 필터들의 모음이다.

즉, FilterChainProxy부터 Spring Security에서 제공하는 보안 필터들이 필요한 작업을 수행하는 것이다.

 

스프링 시큐리티의 필터 체인은 URL 별로 여러 개를 등록할 수 있으며, 필터 체인이 있을 때 어떤 필터 체인을 사용할 지에 대해서는 FilterChainProxy가 결정한다.

반응형