이번 게시물에서는 곧바로 Spring Security
사용법을 알아보기 보다는
이 사용법이 유효하도록 Spring Security Framework
에서 제공하는
핵심 Builder 클래스와 이 Builder 클래스들이 생성한 인스턴스들간의
관계가 어떤지를 가볍게 알아보도록 하겠습니다.
아래와 같은 흐름으로 알아보겠습니다.
저희가 앞으로 배우고, 사용하게 될 Spring Boot Security
설정은 아마
다음 그림과 같이 비슷하게 작성하게 될겁니다.
간단하죠?
HttpSecurity
인스턴스를 파라미터로 받는 @Bean 메소드를 하나 생성하고HttpSecurity
인스턴스가 제공하는 API 로 보안 설정을 해주고build()
메소드를 호출하여 SecurityFilterChain
을 생성 및 반환합니다.추후에 이 SecurityFilterChain
에 저희가 보안적으로 설정한 내용들을
Spring Security
프레임워크가 적시적소에 사용하게 됩니다.
이게 Spring Security 사용법(=설정법)의 전부입니다.
난해하든, 간단하든 위 그림과 비슷한 형태로 출발할 겁니다.
지금부터 나오는 설명들이 약간 복잡할 수 있습니다.
이를 위해서 그림을 하나 준비했습니다.
이 그림을 참고하면서 글을 읽으면 조금 더 따라잡기 쉬우실 거 같습니다
코드를 봐서 알겠지만, 설정의 핵심은 결국 HttpSecurity
라는 것을 알 수 있습니다.
이번에는 HttpSecurity
의 class hierarchy
를 간단하게 관찰해봅시다.
여기서 보면 알겠지만 맨위에 SecurityBuilder 가 존재합니다.
이 인터페이스가 상당히 중요합니다.
SecurityBuilder
는Spring Security
에서 사용되는
핵심적인 인스턴스를 생성하는 빌더 클래스들의 최상위 부모 타입입니다.
앞서 본HttpSecurity
클래스도 그 중 하나입니다.
이 말은 곧 SecurityBuilder
에 의한 class hierarchy
를 어느정도
파악할 수 있으면 전반적인 Spring Security
프레임워크의 동작을 이해할 수 있다는 말이기도 합니다.
지금부터 SecurityBuilder
에 대한 제 분석을 공유하겠습니다.
SecurityBuilder
인터페이스와 관련된 클래스 상속도는 아래와 같습니다.
interface SecurityBuilder
: Spring Security
에서 필요로하는 인스턴스의 생성과 관련된 역할 수행이 핵심입니다.O build() throws Exception;
메소드 시그니쳐 하나만 갖습니다.abstract class AbstractSecurityBuilder
: build
메소드에 의해서 생성되는 인스턴스가 오직 한 개인 것을 보장build
메소드 안에서 실질적인 인스턴스 생성은 doBuild
메소드로 위임protected abstract O doBuild() throws Exception;
는 자식 클래스가 구현abstract class AbstractConfiguredSecurityBuilder
:
AbstractSecurityBuilder
의 기본 구현체이며 doBuild
메소드를 구현doBuild
를 관찰하기 전에 먼저 SecurityConfigurer
를 알아봅시다.interface SecurityConfigurer
:
SecurityBuilder
의 build 메소드를 호출하여 생성되는 인스턴스는
다양한 보안 및 프로세스 설정값들을 가져야 하는데, 이런 설정값을 담는 것이
interface SecurityConfigurer
의 구현체입니다.
AbstractConfiguredSecurityBuilder
클래스는 이러한 구현체의 인스턴스를 List
로 여러개 담아서 필드에 저장합니다.
참고(1) : SecurityConfigurer
는 2개의 메소드 시그니쳐를 갖는다.
void init(B builder) throws Exception;
SecurityConfigurer
들 끼리 공유해서 사용할 인스턴스를 설정ApplicationContext
, SecurityContextRepository
, etc...void configure(B builder) throws Exception;
참고(2) : SecurityConfigurer 의 Java Doc 에서는 반드시 init
이 먼저 호출되고
그 다음으로 configure
가 호출되어야 한다는 문구가 있습니다.
AbstractConfiguredSecurityBuilder
핵심 메소드인 doBuild
를 자세히 보죠.init()
, configure()
메소드는 AbstractConfiguredSecurityBuilder
의List<SecurityConfigurer>
를 순회하면서 각각의 SecurityConfigurer
init
, configure
메소드를 호출하여 보안/프로세스 설정을 마침마지막으로 performBuild()
메소드를 호출하여 SecurityBuilder.build
메소드 호출의 최종 결과물인 인스턴스를 하나 생성
protected abstract O performBuild() throws Exception;
는 자식 클래스가 구현
결국 build()
메소드에 의해서 생성되는 최종적인 인스턴스는
AbstractConfiguredSecurityBuilder.performBuild
메소드이고,
이를 자식클래스가 구현하게 된다는 것을 알게 되었습니다.
그렇다면 performBuild
메소드를 구현한 클래스는 뭐가 있을까?
IDE 의 도움을 받아서 확인해보면 3가지 클래스가 감지됩니다.
각각의 빌더 클래스와 최종적으로 생성하는 인스턴스의 타입이 뭔지를
아래 그림을 통해서 개괄적으로 표현해봤습니다. (클릭해서 크게 보기!)
AuthenticationManagerBuilder
: HttpSecurity
: SecurityFilterChain
타입의 인스턴스를 생성SecurityFilterChain
는 보안처리를 위해 여러 Filter
구현체를 담고 있습니다.HttpSecurity.build
메소드 호출 전까지 설정한 내용에 따라WebSecurity
: FilterChainProxy
타입의 인스턴스를 생성하는 역할을 갖습니다.FilterChainProxy
인스턴스를 springSecurityFilterChain
라는 이름으로 Application Context
에 등록합니다.HttpSecurity.build()
를 통해서 생성한 SecurityFilterChain
FilterChainProxy
입니다.SecurityBuilder
타입 인스턴스가 build 메소드 호출로 생성한
FilterChainProxy
, SecurityFilterChain
는 굉장히 밀접한 관계를 갖습니다.
바로 이전 목차에서 상세히 설명은 안했지만,
결과적으로 FilterChainProxy
와 SecurityFilterChain
간의 구성 관계는 다음과 같습니다.
FilterChainProxy
는 여러 개의 SecurityFilterChain
를 List 로 담는다.SecurityFilterChain
는 여러 개의 Filter
를 List 로 담는다.이러한 구성관계로 Http 요청에 대한 보안 처리는 아래 그림으로 설명을 대신하겠습니다.
아래 그림이 너무 작다고 생각되면 이 링크에 들어가서
HTTP 요청 처리 방식
이라는 제목 밑에 있는 그림을 보시면 되겠습니다.
그런데 위에서 말한 여러 Builder 클래스들은 Spring Boot 의 어떤 자동설정
클래스에서 생성되고 사용될까요?
이는 @EnableWebSecurity
애노테이션에 있는 @Import
애노테이션에 작성된
2개의 클래스에서 확인할 수 있습니다.
너무 세세하게 보지는 않겠습니다!
최대한 가볍게만 관찰해보겠습니다~
먼저 HttpSecurityConfiguration 클래스의 httpSecurity
빈 메소드를 확인해보죠.
기본 AuthenticationManagerBuilder 인스턴스를 생성합니다.
authenitcationManager()
라는 메소드를 호출하여, 결과적으로 아래와 같은 코드를
수행합니다. 중간에 authBuilder.build() 메소드를 호출이 보이시죠?
바로 이때 빌더의 빌드 결과물인 AuthenticationManager
인스턴스가 생성됩니다.
HttpSecurity 빌더 클래스를 생성하고, 몇가지 기본 설정을 해준 후에,
return 하여 다른 곳에서 DI 받아서 사용할 수 있도록 합니다.
개발자가 지정한 Security 설정 클래스
에 의해서 생성된 SecurityFilterChain
인스턴스는 이후에 WebSecurityConfiguration
의 자동설정에 적용됩니다.
앞서 개발자들에 의해서 생성된 SecurityFilterChain
들은 WebSecurityConfiguration
에서 모두 모아서 List<SecurityFilterChain> securityFilterChains
에 넣습니다.
이후에 springSecurityFilterChain()
메소드를 호출하여
미리 생성한 WebSecurity 에 List<SecurityFilterChain> securityFilterChains
를 모두 넣어줍니다.
마지막으로 build 까지 호출하여 FilterChainProxy
타입의 인스턴스를 생성합니다.
이 FilterChainProxy
는 Servlet Engine 으로부터 요청을 가장 앞에서 받는
인스턴스이고, 자신이 갖는 securityFilterChains
중에서 요청을 처리할 수 있는
SecurityFilterChain
인스턴스를 찾아내고 요청을 위임하게 됩니다.
(참고로 FilterChainProxy
는 Filter
클래스를 상속하여 return 타입이 Filter 입니다)
이상으로 글을 마치도록 하겠습니다.
읽으시느라 고생하셨습니다!