Post

[Spring Security] SecurityBuilder์™€ SecurityConfigurer

[Spring Security] SecurityBuilder์™€ SecurityConfigurer

๐Ÿ“Œ ๊ฐœ์š”

Spring Security ๋Š” ์ธ์ฆ/์ธ๊ฐ€ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ filter chain ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค.

SecurityBuilder, SecurityConfigurer ๋Š” ํ•„ํ„ฐ ์ฒด์ธ๊ณผ ๊ด€๋ จ๋œ ๋นˆ๋“ค์„ ๋นŒ๋” ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ์„ฑํ•œ๋‹ค.

๐Ÿ“Œ SecurityBuilder, SecurityConfigurer

1
2
3
4
5
public interface SecurityBuilder<O> {

	O build() throws Exception;

}

SecurityBuilder ๋Š” ์›น ๋ณด์•ˆ์„ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ๋นˆ ๊ฐ์ฒด์™€ ์„ค์ • ํด๋ž˜์Šค๋“ค์„ ์ƒ์„ฑํ•˜๋Š” ๋นŒ๋”์ด๋‹ค. ์ œ๋„ค๋ฆญ ์ธํ„ฐํŽ˜์ด์Šค์ด๋ฉฐ, ๋นŒ๋” ํŒจํ„ด์œผ๋กœ ๋ณด์•ˆ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

๋Œ€ํ‘œ์ ์ธ ๊ตฌํ˜„์ฒด๊ฐ€ ์žˆ๋‹ค. WebSecurity ๋Š” FilterChainProxy ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ์ „์ฒด ์›น ๋ณด์•ˆ ํ•„ํ„ฐ ์ฒด์ธ์„ ๊ด€๋ฆฌํ•˜๋Š” ์ตœ์ƒ์œ„ ํ”„๋ก์‹œ์ด๋‹ค. ignoring ๊ณผ ๊ฐ™์ด ํŠน์ • ์š”์ฒญ์„ ๋ณด์•ˆ ํ•„ํ„ฐ์—์„œ ์•„์˜ˆ ์ œ์™ธํ•˜๋Š” ์ „์—ญ์ ์ธ ์„ค์ •์„ ํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค.

๋˜ ๋‹ค๋ฅธ ๊ตฌํ˜„์ฒด์ธ HttpSecurity๋Š” SecurityFilterChain ์„ ์ƒ์„ฑํ•˜๋ฉฐ, HTTP ์š”์ฒญ์— ๋Œ€ํ•œ ์„ธ๋ถ€์ ์ธ ๋ณด์•ˆ ๊ทœ์น™(์ธ์ฆ/์ธ๊ฐ€, ์„ธ์…˜, CSRF ๋ฐฉ์–ด ๋“ฑ)์„ ์„ค์ •ํ•œ๋‹ค.

1
2
3
4
5
6
public interface SecurityConfigurer<O, B extends SecurityBuilder<O>> {

	void init(B builder) throws Exception;
	void configure(B builder) throws Exception;

}

SecurityConfigurer ๋Š” SecurityBuilder ์— ๊ตฌ์ฒด์ ์ธ ๋ณด์•ˆ ์„ค์ •์„ ์ถ”๊ฐ€ํ•˜๊ณ  ์ปค์Šคํ„ฐ๋งˆ์ด์ง•ํ•œ๋‹ค. formLogin , csrf ์™€ ๊ฐ™์€ ์„ธ๋ถ€์ ์ธ ์„ค์ •์ด ๊ฐ€๋Šฅํ•˜๋ฉฐ ์‹ค์ œ ํ•„ํ„ฐ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.

init ๋ฉ”์„œ๋“œ๋Š” configure ์ „์— ํ•„์š”ํ•œ ๊ณต์œ  ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜ ์ƒํƒœ๋ฅผ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.

configurer ๋ฉ”์„œ๋“œ๋Š” init ์ด ๋ชจ๋‘ ๋๋‚œ ํ›„ ํ˜ธ์ถœ๋˜๋ฉฐ SecurityBuilder ์— ํ•„์š”ํ•œ ์†์„ฑ์„ ์„ค์ •ํ•˜๊ณ  ์‹ค์ œ ํ•„ํ„ฐ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ํ•„ํ„ฐ ์ฒด์ธ์— ์ถ”๊ฐ€ํ•˜๋Š” ๋“ฑ ๊ตฌ์ฒด์ ์ธ ๋ณด์•ˆ ๊ตฌ์„ฑ์„ ์ ์šฉํ•œ๋‹ค.

.formLogin(), .csrf() ์™€ ๊ฐ™์€ ๋ฉ”์„œ๋“œ๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ FormLoginConfigurer ๋‚˜ CsrfConfigurer ์™€ ๊ฐ™์€ SecurityConfigurer ์˜ ๊ตฌํ˜„์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  SecurityBuilder ์— ์ถ”๊ฐ€ํ•œ๋‹ค.

1
2
3
4
5
6
7
8
@Override
public final O build() throws Exception {
	if (this.building.compareAndSet(false, true)) {
		this.object = doBuild();
		return this.object;
	}
	throw new AlreadyBuiltException("This object has already been built");
}

build ๋ฉ”์„œ๋“œ๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ doBuild ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉฐ,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
protected final O doBuild() throws Exception {
	synchronized (this.configurers) {
		this.buildState = BuildState.INITIALIZING;
		beforeInit();
		init();
		this.buildState = BuildState.CONFIGURING;
		beforeConfigure();
		configure();
		this.buildState = BuildState.BUILDING;
		O result = performBuild();
		this.buildState = BuildState.BUILT;
		return result;
	}
}

doBuild ๋ฉ”์„œ๋“œ๋Š” ๋‚ด๋ถ€์—์„œ init ๊ณผ configure ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@SuppressWarnings("unchecked")
private void init() throws Exception {
	Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
	for (SecurityConfigurer<O, B> configurer : configurers) {
		configurer.init((B) this);
	}
	for (SecurityConfigurer<O, B> configurer : this.configurersAddedInInitializing) {
		configurer.init((B) this);
	}
}

@SuppressWarnings("unchecked")
private void configure() throws Exception {
	Collection<SecurityConfigurer<O, B>> configurers = getConfigurers();
	for (SecurityConfigurer<O, B> configurer : configurers) {
		configurer.configure((B) this);
	}
}

init ์™€ configure ๋ฉ”์„œ๋“œ๋Š” ๊ฐ๊ฐ ๋‚ด๋ถ€์ ์œผ๋กœ SecurityConfigurer ์˜ init ๊ณผ configure ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

1
2
3
4
public <C extends SecurityConfigurer<O, B>> C apply(C configurer) throws Exception {
	add(configurer);
	return configurer;
}

AbstractConfiguredSecurityBuilder ์—๋Š” apply ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋Š”๋ฐ, SecurityConfigurer ๋ฅผ SecurityBuilder ๊ตฌํ˜„์ฒด์— ์ถ”๊ฐ€ํ•œ๋‹ค.


SecurityBuilder ์˜ ๋Œ€ํ‘œ์ ์ธ ๊ตฌํ˜„์ฒด๋กœ WebSecurity ์™€ HttpSecurity ๊ฐ€ ์žˆ์—ˆ๋‹ค.

WebSecurity ์˜ build ๋ฉ”์„œ๋“œ๋Š” FilterChainProxy ๋ฅผ ๋ฆฌํ„ดํ•˜๋ฉฐ, HttpSecurity ์˜ build ๋ฉ”์„œ๋“œ๋Š” SecurityFilterChain ์„ ๋ฆฌํ„ดํ•œ๋‹ค.

1
2
3
4
5
6
public class FilterChainProxy extends GenericFilterBean {

	// ...

	private List<SecurityFilterChain> filterChains;
}

FilterChainProxy ๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ SecurityFilterChain ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด SecurityFilterChain์„ ํ†ตํ•ด ์ธ์ฆ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Autowired(required = false)
public void setFilterChainProxySecurityConfigurer(ObjectPostProcessor<Object> objectPostProcessor,
		ConfigurableListableBeanFactory beanFactory) throws Exception {
	this.webSecurity = objectPostProcessor.postProcess(new WebSecurity(objectPostProcessor));
	if (this.debugEnabled != null) {
		this.webSecurity.debug(this.debugEnabled);
	}
	List<SecurityConfigurer<Filter, WebSecurity>> webSecurityConfigurers = new AutowiredWebSecurityConfigurersIgnoreParents(
			beanFactory)
		.getWebSecurityConfigurers();
	webSecurityConfigurers.sort(AnnotationAwareOrderComparator.INSTANCE);
	Integer previousOrder = null;
	Object previousConfig = null;
	for (SecurityConfigurer<Filter, WebSecurity> config : webSecurityConfigurers) {
		Integer order = AnnotationAwareOrderComparator.lookupOrder(config);
		if (previousOrder != null && previousOrder.equals(order)) {
			throw new IllegalStateException("@Order on WebSecurityConfigurers must be unique. Order of " + order
					+ " was already used on " + previousConfig + ", so it cannot be used on " + config + " too.");
		}
		previousOrder = order;
		previousConfig = config;
	}
	for (SecurityConfigurer<Filter, WebSecurity> webSecurityConfigurer : webSecurityConfigurers) {
		this.webSecurity.apply(webSecurityConfigurer);
	}
	this.webSecurityConfigurers = webSecurityConfigurers;
}

WebSecurityConfiguration ๋นˆ์ด ์ƒ์„ฑ๋˜๊ณ  ์ดˆ๊ธฐํ™”๋  ๋•Œ, setFilterChainProxySecurityConfigurer ๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค. ๋ชจ๋“  SecurityConfigurer ๋ฅผ apply ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด WebSecurity ์— ์ถ”๊ฐ€ํ•œ๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@Bean(HTTPSECURITY_BEAN_NAME)
@Scope("prototype")
HttpSecurity httpSecurity() throws Exception {
	LazyPasswordEncoder passwordEncoder = new LazyPasswordEncoder(this.context);
	AuthenticationManagerBuilder authenticationBuilder = new DefaultPasswordEncoderAuthenticationManagerBuilder(
			this.objectPostProcessor, passwordEncoder);
	authenticationBuilder.parentAuthenticationManager(authenticationManager());
	authenticationBuilder.authenticationEventPublisher(getAuthenticationEventPublisher());
	HttpSecurity http = new HttpSecurity(this.objectPostProcessor, authenticationBuilder, createSharedObjects());
	WebAsyncManagerIntegrationFilter webAsyncManagerIntegrationFilter = new WebAsyncManagerIntegrationFilter();
	webAsyncManagerIntegrationFilter.setSecurityContextHolderStrategy(this.securityContextHolderStrategy);
	// @formatter:off
	http
		.csrf(withDefaults())
		.addFilter(webAsyncManagerIntegrationFilter)
		.exceptionHandling(withDefaults())
		.headers(withDefaults())
		.sessionManagement(withDefaults())
		.securityContext(withDefaults())
		.requestCache(withDefaults())
		.anonymous(withDefaults())
		.servletApi(withDefaults())
		.apply(new DefaultLoginPageConfigurer<>());
	http.logout(withDefaults());
	// @formatter:on
	applyDefaultConfigurers(http);
	return http;
}

WebSecurityConfiguration ๋ฅผ ํ†ตํ•ด FilterChainProxy ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด SecurityFilterChain ๋นˆ์„ ์ˆ˜์ง‘ํ•ด์•„ ํ•œ๋‹ค. ์ด ๊ณผ์ •์—์„œ HttpSecurity ๊ฐ€ ํ•„์š”ํ•˜๋ฏ€๋กœ, HttpSecurityConfiguration ์˜ httpSecurity ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค. ๋ฉ”์„œ๋“œ ์ฒด์ด๋‹์„ ํ†ตํ•ด HttpSecurity ๊ฐ์ฒด์— ์—ฌ๋Ÿฌ SecurityConfigurer ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

1
2
3
4
5
public HttpSecurity csrf(Customizer<CsrfConfigurer<HttpSecurity>> csrfCustomizer) throws Exception {
	ApplicationContext context = getContext();
	csrfCustomizer.customize(getOrApply(new CsrfConfigurer<>(context)));
	return HttpSecurity.this;
}

csrf ๋ฉ”์„œ๋“œ๋ฅผ ๋ณด๋ฉด, getOrApply ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด CsrfConfigurer ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ๋‚˜๋จธ์ง€ ๋ฉ”์„œ๋“œ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ ์ ˆํ•œ SecurityConfigurer ๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Configuration(proxyBeanMethods = false)
@ConditionalOnDefaultWebSecurity
static class SecurityFilterChainConfiguration {

	@Bean
	@Order(SecurityProperties.BASIC_AUTH_ORDER)
	SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
		http.authorizeHttpRequests((requests) -> requests.anyRequest().authenticated());
		http.formLogin(withDefaults());
		http.httpBasic(withDefaults());
		return http.build();
	}

}

์ดํ›„ httpSecurity ๋ฉ”์„œ๋“œ์—์„œ ๋ฆฌํ„ด๋œ HttpSecurity ๋Š” SecurityFilterChainConfiguration ์˜ build ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด SecurityFilterChain ์— ์ฃผ์ž…๋œ๋‹ค.

1
2
3
4
@Autowired(required = false)
void setFilterChains(List<SecurityFilterChain> securityFilterChains) {
	this.securityFilterChains = securityFilterChains;
}

๋งŒ๋“ค์–ด์ง„ SecurityFilterChain ์€ WebSecurityConfiguration ์˜ setFilterChains ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์„ค์ •๋œ๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@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();
}

์„ค์ •๋œ SecurityFilterChain ์€ springSecurityFilterChain ๋ฉ”์„œ๋“œ์—์„œ ๋นŒ๋” ํ˜•ํƒœ๋กœ ๊ฐ์‹ธ์„œ WebSecurity ์— ์ถ”๊ฐ€ํ•œ๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Override
protected Filter performBuild() throws Exception {

	// ...
	
	for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : this.securityFilterChainBuilders) {
		SecurityFilterChain securityFilterChain = securityFilterChainBuilder.build();
		securityFilterChains.add(securityFilterChain);
		requestMatcherPrivilegeEvaluatorsEntries
			.add(getRequestMatcherPrivilegeEvaluatorsEntry(securityFilterChain));
	}
	if (this.privilegeEvaluator == null) {
		this.privilegeEvaluator = new RequestMatcherDelegatingWebInvocationPrivilegeEvaluator(
				requestMatcherPrivilegeEvaluatorsEntries);
	}
	FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
	
	// ...
}

performBuild ๋ฉ”์„œ๋“œ๋Š” WebSecurity ๊ฐ์ฒด์˜ build ๋ฉ”์„œ๋“œ ๋‚ด๋ถ€์—์„œ ํ˜ธ์ถœ๋œ๋‹ค. addSecurityFilterChainBuilder ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์ˆ˜์ง‘ํ•œ SecurityFilterChain ์˜ ๋นŒ๋”๋ฅผ ๋‹ค์‹œ SecurityFilterChain ๊ฐ์ฒด๋กœ ๋ฆฌํ„ด๋ฐ›๊ณ , ์ด๋“ค์„ ํ†ตํ•ด FilterChainProxy ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

๐Ÿ“Œ ๋™์ž‘ ๊ณผ์ •

์ „์ฒด์ ์ธ ๋™์ž‘ ๊ณผ์ •์„ ์ •๋ฆฌํ•˜์—ฌ ์‚ดํŽด๋ณด์ž.

  1. WebSecurityConfiguration, HttpSecurityConfiguration ๊ณผ ๊ฐ™์€ ์„ค์ • ํŒŒ์ผ์ด IoC ์ปจํ…Œ์ด๋„ˆ์— ๋กœ๋“œ๋œ๋‹ค.
  2. WebSecurityConfiguration ๋นˆ์„ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ๊ณผ์ •์—์„œ setFilterChainProxySecurityConfigurer ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๊ณ , WebSecurity ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค.
  3. ์กด์žฌํ•˜๋Š” ๋ชจ๋“  WebSecurityConfigurer ํƒ€์ž…์˜ ๋นˆ์„ ์ฐพ๊ณ , apply ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด WebSecurity ๋นŒ๋”์— ์ ์šฉํ•œ๋‹ค.
  4. ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋œ SecurityFilterChain ์„ ์ฐพ๋Š”๋‹ค. ๋‹จ, SecurityFilterChain ๋นˆ์„ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ HttpSecurity ๊ฐ์ฒด๊ฐ€ ํ•„์š”ํ•˜๋ฏ€๋กœ HttpSecurityConfiguration ์˜ httpSecurity ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์ƒˆ๋กœ์šด HttpSecurity ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ํŒŒ๋ผ๋ฏธํ„ฐ์— ์ฃผ์ž…ํ•œ๋‹ค.
  5. ์ฃผ์ž…๋ฐ›์€ http ๊ฐ์ฒด์— ๋ฉ”์„œ๋“œ ์ฒด์ด๋‹์„ ํ†ตํ•ด ๋ณด์•ˆ ์„ค์ •์„ ์ ์šฉํ•˜๊ณ , build ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
  6. build ๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ doBuild ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ init ๊ณผ configure ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋ณด์•ˆ ํ•„ํ„ฐ๋ฅผ ๊ตฌ์„ฑํ•˜๊ณ , ์ด๋“ค์„ ๋‹ด์€ SecurityFilterChain ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ๋ฆฌํ„ดํ•œ๋‹ค. ์ƒ์„ฑ๋œ SecurityFilterChain ๊ฐ์ฒด๋Š” ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋œ๋‹ค.
  7. ๋‹ค์‹œ 3๋ฒˆ ๋™์ž‘์—์„œ, setFilterChains ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์กด์žฌํ•˜๋Š” ๋ชจ๋“  SecurityFilterChain ๋นˆ๋“ค์„ ํ•˜๋‚˜์˜ List ๋กœ ๋ฌถ๋Š”๋‹ค.
  8. ์ดํ›„ springSecurityFilterChain ๋ฉ”์„œ๋“œ์—์„œ ์ฃผ์ž…๋ฐ›์€ securityFilterChains ๋ฆฌ์ŠคํŠธ๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ SecurityFilterChain ๊ฐ์ฒด๋ฅผ ๋นŒ๋” ํ˜•ํƒœ๋กœ ๊ฐ์‹ธ WebSecurity ๊ฐ์ฒด์— ๋“ฑ๋กํ•œ๋‹ค.
  9. ๋ชจ๋‘ ๋“ฑ๋ก๋˜๋ฉด WebSecurity ์˜ build ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ performBuild ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
  10. performBuild ๋ฉ”์„œ๋“œ์—์„œ ๋นŒ๋” ํ˜•ํƒœ๋กœ ๊ฐ์‹ผ SecurityFilterChain ์„ ๋‹ค์‹œ ์›๋ž˜ SecurityFilterChain ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•œ ํ›„, ์ด๋“ค์„ ํ†ตํ•ด ์ตœ์ข… FilterChainProxy ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•œ๋‹ค. ์ƒ์„ฑ๋œ FilterChainProxy ๊ฐ์ฒด๋Š” ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ์˜ ๋นˆ์œผ๋กœ ๋“ฑ๋ก๋œ๋‹ค.

๐Ÿ“Œ ์ฐธ๊ณ 

https://ttl-blog.tistory.com/1165

This post is licensed under CC BY 4.0 by the author.