[Spring Security] 3. SecurityFilterChain 등록

조성우·2024년 7월 31일

Spring Security

목록 보기
3/16
post-thumbnail

스프링 시큐리티 의존성을 추가하면 기본적으로 DefaultSecurityFilterChain이 하나 등록된다. 해당 SecurityFilterChain을 알아보기 전에, 커스텀 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 디버깅을 통해 등록 확인

2개 이상의 SecurityFilterChain

FilterChainProxy는 N개의 SecurityFilterChain 중 하나를 선택해 요청을 전달한다.

기준

  • 등록 인덱스 순
  • 필터 체인의 RequestMatcher 값 일치 여부


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 securityMatchers to determine if a given HttpSecurity should be applied to a given request


SecurityFilterChain 순서 설정 (선택 사항)

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

0개의 댓글