μ΄λ²μλ SecurityFilterChain μ λ±λ‘ κ³Όμ μ λνμ¬ λΆμν΄λ³΄μ.
Default SecurityFilterChain
Spring Security μ λν Dependency λ₯Ό μ€μ νλ©΄ κΈ°λ³Έμ μΈ SecurityFilterChain μ΄ νλ μμ±λλ€.

μ΄μ κΈμμ FilterChainProxy λ SecurityFilterChain λ€μ List ννλ‘ κ΄λ¦¬νλ€κ³ νλ€. μ€μ λ‘ κ΅¬νμ μ΄ν΄λ³΄λ©΄ μμ κ°μ΄ List λ‘ λμ΄μλ κ²μ λ³Ό μ μλ€.
FilterChainProxy.class μμ getFitlers() method μ breakpoint λ₯Ό κ±Έκ³ Debug λͺ¨λλ‘ μ€ννκ³ , κ°λ¨ν request λ₯Ό 보λ΄λ³΄λ©΄ μλμ κ°μ΄ filterChains μ size κ° 1, μ¦ κΈ°λ³Έμ μΌλ‘ νλμ SecurityFilterChain μ΄ μ‘΄μ¬νλ κ²μ λ³Ό μ μλ€.

Custom SecurityFilterChain
μ΄λ²μλ Custom SecurityFilterChain μ λνμ¬ μμ보μ.
Custom SecurityFilterChain μ λ±λ‘νλ λ°©λ²μ SecurityConfig class λ₯Ό μ§μ ꡬμ±νλ κ²μ΄λ€.
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// Filter Chains ...
return http.build();
}μμ κ°μ΄ SecurityFilterChain type μ Bean μ define νμ¬ Custom SecurityFilterChain μ λ±λ‘ν μ μμΌλ©°, μ¬λ¬ κ°λ₯Ό define νμ¬ μ¬λ¬ κ°μ SecurityFilterChain μ λ±λ‘ν μ μλ€. μ¬λ¬ κ°λ₯Ό λ±λ‘ν κ²½μ°, μλμ κ°μ΄ size κ° λμ΄λ κ²μ λ³Ό μ μλ€.

private List<SecurityFilterChain> filterChains;λν μμμ μΈκΈν κ²μ²λΌ FilterChainProxy λ μ¬λ¬ κ°μ SecurityFilterChain λ€μ List ννλ‘ κ΄λ¦¬νλλ°, index μ μμλ @Order(n) μ ν΅νμ¬ λͺ
μμ μΌλ‘ μ§μ νμ§ μλ μ΄μ λ±λ‘ μμλ 보μ₯μ΄ λμ§ μλλ€.
Multi-SecurityFilterChain νκ²½
μ¬λ¬ κ°μ SecurityFilterChain μ΄ μ‘΄μ¬νλ νκ²½μμλ μ΄λ€ κΈ°μ€μΌλ‘ νΉμ SecurityFilterChain μ μ ννμ¬ request λ₯Ό μ λ¬νλ κ²μΌκΉ? μ°μ μ λ€μ κΈ°μ€μ λ°λ₯Έλ€.
- λ±λ‘λ index μ
- Filter Chain μ λν
RequestMatcherκ°μ μΌμΉ μ¬λΆ
RequestMatcher λ λ€μ΄μ€λ request μ URL, HTTP Method, Header λ±μ κΈ°μ€μΌλ‘ matching νμ¬, ν΄λΉ request μλ§ Security Rule μ μ μ©ν μ μκ² λμμ£Όλ λ°μ μ¬μ©λλ Interface μ΄λ€.
RequestMatcher λ μ£Όλ‘ λ€μκ³Ό κ°μ μν©μμ μ¬μ©νλ€.
securityMatcher:SecurityFilterChainμ΄ μμ μ μ©λ request μ κ²½λ‘λ₯Ό μ§μ authorizeHttpRequests(): μ΄λ―ΈSecurityFilterChainμ΄ μ μ©λ request λ€ μ€μμ, κ° κ²½λ‘λ κΆν λ±μ 쑰건λ³λ‘ Authorization κ·μΉμ μΈλΆμ μΌλ‘ μ§μ , μ£Όλ‘.requestMatchers()λ₯Ό μ¬μ©νμ¬ μ‘°κ±΄μ μ€μ
λ¬Έμ μν©
@Bean
public SecurityFilterChain adminChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((auth) -> auth
.requestMatchers("/admin").permitAll());
return http.build();
}
@Bean
public SecurityFilterChain publicChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((auth) -> auth
.requestMatchers("/user").permitAll());
return http.build();
}μ°μ μμ κ°μ΄ λ κ°μ SecurityFilterChain μ λ±λ‘νλ€κ³ κ°μ ν΄λ³΄μ. κ°κ° requestMatchers() λ₯Ό μ¬μ©νμ¬ νλλ /admin κ²½λ‘μ, λ€λ₯Έ νλλ /user κ²½λ‘μ λν request λ₯Ό μ²λ¦¬νλλ‘ λμ΄ μλ κ² κ°λ€.
κ·Έλ¬λ securityMatcher λ₯Ό μ¬μ©νμ§ μλλ€λ©΄ ν΄λΉ SecurityFilterChain μ /**, μ¦ λͺ¨λ request κ²½λ‘μ λνμ¬ μ μ©λλ€. μμ κ°μ΄ λͺ¨λ SecurityFilterChain μ΄ securityMatcher λ₯Ό μ¬μ©νμ§ μκ³ μλ€λ©΄, FilterChainProxy κ° κ΄λ¦¬νλ SecurityFilterChain λ€ μ€, index κ° λ μμ SecurityFilterChain μ΄ μ νλλ€. λ μ½κ² λ§νλ©΄ /admin μΌλ‘ request λ₯Ό λ°λ, /user λ‘ request λ₯Ό λ°λ λͺ¨λ index κ° λ μμ SecurityFilterChain μ΄ μ μ©λλ€λ λ»μ΄λ€.
λ§μ½ adminChain μ΄ index 0 μ λ±λ‘λμ΄ μλ€λ©΄, /user κ²½λ‘μ λνμ¬ request λ₯Ό 보λ΄λ adminChain μ΄ μ μ©λ κ²μ΄λ€. ν΄λΉ SecurityChainFilter μλ /user κ²½λ‘μ λν λ³λμ μ²λ¦¬ κ³Όμ μ΄ λͺ
μλμ΄ μμ§ μμΌλ―λ‘ /user request λ 무μλ κ²μ΄λ€.
λ€νν μ΅μ λ²μ μ Spring Security(6.x) μμλ μ¬λ¬ κ°μ SecurityFilterChain λ₯Ό define ν λ, κ° Chain μ΄ μ΄λ€ request μ μ μ©λ μ§ λͺ
μμ μΌλ‘ μ§μ νμ§ μμΌλ©΄, μ¦ securityMatcher λ₯Ό μ¬μ©νμ§ μμΌλ©΄ Application μ€νμμ μ€λ₯λ₯Ό λ°μμν¨λ€.
ν΄κ²°
@Bean
public SecurityFilterChain adminChain(HttpSecurity http) throws Exception {
http
.securityMatcher("/admin")
.authorizeHttpRequests((auth) -> auth
.requestMatchers("/admin").permitAll());
return http.build();
}
@Bean
public SecurityFilterChain publicChain(HttpSecurity http) throws Exception {
http
.securityMatcher("/user")
.authorizeHttpRequests((auth) -> auth
.requestMatchers("/user").permitAll());
return http.build();
}μ΄ λ¬Έμ μ λν ν΄κ²°μ κ°λ¨νλ€. κ° SecurityFilterChain μ λνμ¬ securityMatcher λ₯Ό μ¬μ©νμ¬ μ μ©λ request μ κ²½λ‘λ₯Ό λͺ
μμ μΌλ‘ μ§μ νλ©΄ λλ€.
λ±λ‘ μμλ₯Ό 보μ₯νλ λ°©λ²
@Bean
@Order(1)
public SecurityFilterChain adminChain(HttpSecurity http) throws Exception {
// ...
return http.build();
}
@Bean
@Order(2)
public SecurityFilterChain publicChain(HttpSecurity http) throws Exception {
// ...
return http.build();
}μμ μ¬λ¬ κ°μ SecurityFilterChain μ λ±λ‘νλ©΄ μμκ° λ³΄μ₯λμ§ μλλ€κ³ μΈκΈνμλ€. μ΄μ λνμ¬ @Order(n) annotation μ μ¬μ©νμ¬ μμλ₯Ό μ§μ ν μ μλ€.
μλμ μΌλ‘ SecurityFilterChain μ κ±°μΉμ§ μλ λ°©λ²
λ§μ½ request κ²½λ‘κ° μ μ μμ(image file, CSS, HTML λ±)μ ν΄λΉνλ€λ©΄ κ΅³μ΄ λͺ¨λ SecurityFilterChain μμ SecurityFilter λ€μ κ±°μ³μΌν κΉ?
μ°μ μ μ μμ(Static Resources)λ€μ 곡κ°λμ΄μΌ ν file λ€μ΄λ€. λ°λΌμ κ±°μΉ νμκ° μλ€.
λν μ±λ₯ μΈ‘λ©΄μμ μ 리νλ€. μ μ μμλ€μ κ·Έλ₯ μλ²μμ λ³λ μ²λ¦¬ κ³Όμ μμ΄ ν΄λΉ μμλ§ response ν΄μ£Όλ©΄ λλ€. μ μ ν SecurityFilterChain λ₯Ό μ ννλ κ²μλ μλ²μ μμμ΄ μ°μ΄κ³ , μ μ ν SecurityFilterChain μ μ°Ύμ νμλ λ΄λΆμ λͺ¨λ SecurityFilter λ€μ κ±°μΉλ κ²μλ μμμ΄ μ°μΈλ€.
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return web -> web.ignoring().requestMatchers("/img/**");
}μμ κ°μ΄ WebSecurityCustomizer μ λν Bean μ SecurityConfig class μ μΆκ°ν΄μ£Όλ©΄, λ΄λΆμ SecurityFilter κ° μ‘΄μ¬νμ§ μμ μλ‘μ΄ SecurityFilterChain μ΄ index 0 λ²μΌλ‘ λ±λ‘λλ€.

μ€μ λ‘ ν
μ€νΈν΄λ³΄λ©΄ μ νν 0 λ² index μ ν΄λΉ SecurityFilterChain μ΄ λ±λ‘λ κ²μ λ³Ό μ μλ€.