Spring Security | 01 | DelegatingFilterProxy, FilterChainProxy

XingXi·2023년 11월 10일
1

Spring Security

목록 보기
1/1
이번 사이드 프로젝트를 통해 Spring Security 를 사용해보았습니다.

🍔 Spring Security , Authentication, Authorization

Spring Security Reference

Spring Security

Spring Security is a framework that provides authentication, authorization, and protection against common attacks. With first class support for securing both imperative and reactive applications, it is the de-facto standard for securing Spring-based applications.

For a complete list of features, see the Features section of the reference.

Authentication

Spring Security provides comprehensive support for authentication. Authentication is how we verify the identity of who is trying to access a particular resource. A common way to authenticate users is by requiring the user to enter a username and password. Once authentication is performed we know the identity and can perform authorization.

Spring Security provides built-in support for authenticating users. This section is dedicated to generic authentication support that applies in both Servlet and WebFlux environments. See the sections on authentication for Servlet and WebFlux for details on what is supported for each stack.

Authorization

Spring Security provides comprehensive support for authorization. Authorization is determining who is allowed to access a particular resource. Spring Security provides defense in depth by allowing for request based authorization and method based authorization.

Authentication : 신원 확인 ex) 로그인
Authorization : 해당 인원의 접근 권한 확인 ex) 로그인한 사용자가 관리자인지 아닌지 확인

인증( Authentication ), 인가 ( Authorization ) 및 보안 기능을 제공하는 Spring 하위 프레임 워크를 말합니다.

🍗 Architecture, Security Filter Chain

Spring Security Architecture Reference
DelegatingFilterChain, FilterChainProxy Reference

A Review of Filters

Spring Security’s Servlet support is based on Servlet Filters, so it is helpful to look at the role of Filters generally first. The following image shows the typical layering of the handlers for a single HTTP request.The client sends a request to the application, and the container creates a FilterChain, which contains the Filter instances and Servlet that should process the HttpServletRequest, based on the path of the request URI. In a Spring MVC application, the Servlet is an instance of DispatcherServlet. At most, one Servlet can handle a single HttpServletRequest and HttpServletResponse. However, more than one Filter can be used to:
Prevent downstream Filter instances or the Servlet from being invoked. In this case, the Filter typically writes the HttpServletResponse.
Modify the HttpServletRequest or HttpServletResponse used by the downstream Filter instances and the Servlet.The power of the Filter comes from the FilterChain that is passed into it.

사용자가 어플리케이션에 요청할 때마다 Servlet 객체와 Filter 들이 포함된 FilterChain 을 생성합니다.
해당 Servlet 객체는 DispatchatcherSerlvet 의 인스턴스임으로
사용자가 요청하기 전 Filter 가 먼저 작동하는 것을 알 수 있습니다.
즉, SpringSecurity 는 Servlet 에 요청이 도달하기 전에 인증, 인가 및 보안 기능을 수행합니다.
그렇다면 Spring Security 의 Filter 에 대해서 알아봅시다!

DelegatingFilterProxy

Spring provides a Filter implementation named DelegatingFilterProxy that allows bridging between the Servlet container’s lifecycle and Spring’s ApplicationContext. The Servlet container allows registering Filter instances by using its own standards, but it is not aware of Spring-defined Beans. You can register DelegatingFilterProxy through the standard Servlet container mechanisms but delegate all the work to a Spring Bean that implements Filter.Here is a picture of how DelegatingFilterProxy fits into the Filter instances and the FilterChain.DelegatingFilterProxy looks up Bean Filter0 from the ApplicationContext and then invokes Bean Filter0.

FilterChainProxy

Spring Security’s Servlet support is contained within FilterChainProxy. FilterChainProxy is a special Filter provided by Spring Security that allows delegating to many Filter instances through SecurityFilterChain. Since FilterChainProxy is a Bean, it is typically wrapped in a DelegatingFilterProxy.
The following image shows the role of FilterChainProxy.

🥩DelegatingFilterProxy


Servlet Container 의 생명주기와 Spring Application Context 를 브릿징을 허용해주는 Spring 에서 제공하는 Filter 입니다.
Servlet Filter 에도 Spring 기술을 사용하기 위해서 Filter 를 Spring Bean 으로 만들어 주입받아서 사용할 수 있게 구성했습니다.
하지만 이렇게 만들어진 Filter 는 Spring Bean 으로만 등록이 되어있기 때문에 필터로써의 역할을 할수 없습니다.
따라서 Servlet Filter 중에서 Servlet Filter 와 Spring Bean 으로 등록된 필터를 연결시켜주는 필터가 필요하고,
그 필터가 DelegatingFilterProxy 입니다
.

  • DelegatingFilterProxy 는 Serlvet Filter 로 요청이 오면 Spring Bean 으로 등록된 Filter를 찾아서 요청을 위임하는 역할을 합니다 ( 자신한테 요청이 오면 Spring Bean 으로 등록된 Bean 에게 요청 짬 때리는 역할 )

🥩FilterChainProxy


DelegatingFilterProxy 에서 호출된 Spring Bean 이자 Filter 입니다. Spring Security 에서 제공하는 Filter 이며
Spring Bean 이면서 Servlet Filter 를 구현합니다. SecurityFilterChain 을 호출하여 인증/ 인가 및 보안 기능을 수행합니다.
Servlet 과 Security Filter 의 경계 역할을 하고,
어떤 Spring Security Filter Chain 을 사용할 지 결정합니다.
필터는 순차적으로 실행되며, 마지막 필터까지 예외가 발생하지 않으면 요청을 다시 DispatchServlet 으로 넘깁니다.

  • FilterChainProxySpring Security 에서 제공하는 Filter 이며
  • DelegatingFilterProxy 에 의해 호출된 Spring Bean 이며 Filter 이고
  • Servlet 과 Spring Security Chain의 경게 역할을 하며
  • 어떤 Security Filetr Chain 을 사용할지 결정합니다
  • SecurityFilterChain 을 사용하여 Spring Security 의 핵심 기능을 구현합니다.
  • SecurityFilterChain 안의 필터들이 순차적으로 실행되고
  • 예외가 발생하지 않으면 DispatchServlet 로 요청이 반환됩니다.

🍕Stream

  1. Client 가 Applicatioin에 요청
  2. 요청이 오면 인증,인가 및 보안 기능을 수행하기 위해 DelegatingFilterProxy 가 실행 됩니다.
  3. DelegatingFilterProxy 내부의 Spring Bean 인 FilterChainProxy가 호출 됩니다.
  4. FilterChainProxy 에서 관리하는 SecurityFilterChain 들 중 선택하여 Security 기능을 수행합니다.

🥩SecurityFilterAutoConfiguration

@AutoConfiguration(after = SecurityAutoConfiguration.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(SecurityProperties.class)
@ConditionalOnClass({ AbstractSecurityWebApplicationInitializer.class, SessionCreationPolicy.class })
public class SecurityFilterAutoConfiguration {

	private static final String DEFAULT_FILTER_NAME = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME;

	@Bean
	@ConditionalOnBean(name = DEFAULT_FILTER_NAME)
	public DelegatingFilterProxyRegistrationBean securityFilterChainRegistration(
			SecurityProperties securityProperties) {
		DelegatingFilterProxyRegistrationBean registration = new DelegatingFilterProxyRegistrationBean(
				DEFAULT_FILTER_NAME);
		registration.setOrder(securityProperties.getFilter().getOrder());
		registration.setDispatcherTypes(getDispatcherTypes(securityProperties));
		return registration;
	}

	private EnumSet<DispatcherType> getDispatcherTypes(SecurityProperties securityProperties) {
		if (securityProperties.getFilter().getDispatcherTypes() == null) {
			return null;
		}
		return securityProperties.getFilter()
			.getDispatcherTypes()
			.stream()
			.map((type) -> DispatcherType.valueOf(type.name()))
			.collect(Collectors.toCollection(() -> EnumSet.noneOf(DispatcherType.class)));
	}

}

🥩AbstractSecurityWebApplicationInitializer

 * @author Rob Winch
 * @author Keesun Baik
 */
public abstract class AbstractSecurityWebApplicationInitializer implements WebApplicationInitializer {

	private static final String SERVLET_CONTEXT_PREFIX = "org.springframework.web.servlet.FrameworkServlet.CONTEXT.";

	public static final String DEFAULT_FILTER_NAME = "springSecurityFilterChain";

	private final Class<?>[] configurationClasses;

	/**

🥩WebSecurityConfiguration

/**
 * Uses a {@link WebSecurity} to create the {@link FilterChainProxy} that performs the web
 * based security for Spring Security. It then exports the necessary beans. Customizations
 * can be made to {@link WebSecurity} by implementing {@link WebSecurityConfigurer} and
 * exposing it as a {@link Configuration} or exposing a {@link WebSecurityCustomizer}
 * bean. This configuration is imported when using {@link EnableWebSecurity}.
 *
 * @author Rob Winch
 * @author Keesun Baik
 * @since 3.2
 * @see EnableWebSecurity
 * @see WebSecurity
 */
@Configuration(proxyBeanMethods = false)
public class WebSecurityConfiguration implements ImportAware, BeanClassLoaderAware {
...

	/**
	 * Creates the Spring Security Filter Chain
	 * @return the {@link Filter} that represents the security filter chain
	 * @throws Exception
	 */
	@Bean(name = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME)
	public Filter springSecurityFilterChain() throws Exception {
		boolean hasFilterChain = !this.securityFilterChains.isEmpty();
		if (!hasFilterChain) {
			this.webSecurity.addSecurityFilterChainBuilder(() -> {
				this.httpSecurity.authorizeHttpRequests((authorize) -> authorize.anyRequest().authenticated());
				this.httpSecurity.formLogin(Customizer.withDefaults());
				this.httpSecurity.httpBasic(Customizer.withDefaults());
				return this.httpSecurity.build();
			});
		}
		for (SecurityFilterChain securityFilterChain : this.securityFilterChains) {
			this.webSecurity.addSecurityFilterChainBuilder(() -> securityFilterChain);
		}
		for (WebSecurityCustomizer customizer : this.webSecurityCustomizers) {
			customizer.customize(this.webSecurity);
		}
		return this.webSecurity.build();
	}
  1. Spring Application 실행 시 SecurityFilterAutoConfiguration 클래스가 호출되고
  2. DelegatinFilterProxyRegistrationBean 이 생성 될 때 "springSecurityFilterChain" 라는 이름으로 생성됩니다.

🍟 SUMMARY

Spring SecurityFilter 를 사용하여 인증 인가 보안 등의 기능을 제공하는 프레임 워크이며, DelegatingFilterProxy 를 통해 Spring Bean 으로 등록된 필터 ( FilterChainProxy ) 를 호출하여 Spring Security 기능을 수행

다음에는 SecurityFilterChain 에 대해서 알아보겠습니다!

0개의 댓글