
스프링 시큐리티 의존성을 추가하면 기본적으로 DefaultSecurityFilterChain이 하나 등록된다. 해당 SecurityFilterChain을 알아보기 전에, 커스텀 SecurityFilterChain을 등록하는 방법을 알아보자.
SecurityFilterChain을 등록하기 위해서는 SecurityFilterChain을 리턴하는 @Bean 메소드를 등록하면 된다. (한 개 이상 등록 가능)
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain1(HttpSecurity http) throws Exception{
return http.build();
}
@Bean
public SecurityFilterChain filterChain2(HttpSecurity http) throws Exception {
return http.build();
}
}
FilterChainProxy 디버깅을 통해 등록 확인

FilterChainProxy는 N개의 SecurityFilterChain 중 하나를 선택해 요청을 전달한다.
기준
문제 상황
2개 이상의 SecurityFilterChain을 등록할 시, 모든 SecurityFilterChain이 "/**" 경로에서 매핑된다. 즉, 첫 번째로 등록된 SecurityFilterChain만 통과하게 된다.
@Bean
public SecurityFilterChain filterChain1(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((auth) -> auth
.requestMatchers("/user").permitAll());
return http.build();
}
@Bean
public SecurityFilterChain filterChain2(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((auth) -> auth
.requestMatchers("/admin").permitAll());
return http.build();
}
위의 2개의 커스텀 SecurityFilterChain을 등록하고 “/user”, “/admin” 경로에 대해서 permitAll() 설정을 진행한다.
이후 “/admin” 경로로 요청을 보내면 별다른 인증 과정 없이 “/admin” 컨트롤러의 데이터를 획득할 수 있다고 생각하지만 시큐리티의 매핑 자체가 없어서 잘못된 응답이 발생한다.
해결 방법 - SecurityFilterChain에 대한 경로 매핑 : securityMatchers
@Bean
public SecurityFilterChain filterChain1(HttpSecurity http) throws Exception {
http
.securityMatchers((auth) -> auth.requestMatchers("/user"));
http
.authorizeHttpRequests((auth) -> auth
.requestMatchers("/user").permitAll());
return http.build();
}
@Bean
public SecurityFilterChain filterChain2(HttpSecurity http) throws Exception {
http
.securityMatchers((auth) -> auth.requestMatchers("/admin"));
http
.authorizeHttpRequests((auth) -> auth
.requestMatchers("/admin").authenticated());
return http.build();
}
We use
securityMatchersto determine if a given HttpSecurity should be applied to a given request
N개의 SecurityFilterChain을 등록 한 뒤, 등록되는 순서를 직접 정해주고 싶은 경우 @Order() 어노테이션에 값을 명시할 수 있다.
@Bean
@Order(1)
public SecurityFilterChain filterChain1(HttpSecurity http) throws Exception{
return http.build();
}
@Bean
@Order(2)
public SecurityFilterChain filterChain2(HttpSecurity http) throws Exception {
return http.build();
}
SecurityFilterChain을 거치게 된다면 내부적으로 여러 가지 필터를 거치게 되는데, 이때 서버의 자원을 사용하고 상주 시간이 발생하기 때문에 원하는 값은 필터를 통과하지 못하도록 설정할 수 있다.
보통 정적 자원(이미지, CSS)의 경우 필터를 통과하지 않도록 아래처럼 설정할 수 있다.
@Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return web -> web.ignoring().requestMatchers("/img/**");
}
설정 시 하나의 SecurityFilterChain이 0번 인덱스로 설정되며 해당 필터 체인 내부에는 필터가 없는 상태로 생성된다.
※ 참고
Spring Security - Authorization - Authorize HttpServletRequests