본문 바로가기

Java Kotlin

[Java/SpringBoot] Spring Security 사용 시 특정 url들의 필터 무시가 작동되지 않았던 문제

문제 상황 & 코드

특정 url들은 보안 필터를 거치지 않도록 설정했으나, 해당 설정이 먹히지 않는 현상이 발생했다.

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Autowired
    private TokenProvider tokenProvider;
    private final String[] allowedUrls = {"/", "/nickname/**", "/sign-up/**", "/sign-in/**"};

    // H2 콘솔 사용을 위한 설정
    @Bean
    @ConditionalOnProperty(name = "spring.h2.console.enabled", havingValue = "true")
    public WebSecurityCustomizer configureH2ConsoleEnable() {
        return web -> web.ignoring()
                .requestMatchers(PathRequest.toH2Console());
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
                .csrf(AbstractHttpConfigurer::disable)  // 쿠키 사용 안 함
                .authorizeHttpRequests(requests ->
                        requests.requestMatchers(allowedUrls).permitAll()    // requestMatchers의 인자로 전달된 url은 모두에게 허용
                                .anyRequest().authenticated()    // 그 외의 모든 요청은 인증 필요
                )
                .sessionManagement(sessionManagement ->
                        sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                )    // 세션을 사용하지 않으므로 STATELESS 설정
                .addFilterBefore(new JwtAuthenticateFilter(tokenProvider),
                        UsernamePasswordAuthenticationFilter.class)
                .build();
    }
}

 


해결 방법

allowedUrls에 있는 url들이 보안 필터를 거치는 것은 WebSecurityCustomizer와 SecurityFilterChain의 우선순위 때문이었다. WebSecurityCustomizer가 먼저 실행되고, 이후 남는 url들은 SecurityFilterChain을 거친다.

그래도 SecurityFilterChain에서 설정한 것들도 같이 적용되어야 하는 거 아닌가라는 의문이 남기는 하지만...........

 

일단 WebSecurityCustomizer는 전체 보안 설정을 무시하는 것에 사용되므로 allowedUrls를 WebSecurityCustomizer로 옮겨주어 해결하였다.

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Autowired
    private TokenProvider tokenProvider;
    private final String[] allowedUrls = {"/", "/nickname/**", "/sign-up/**", "/sign-in/**"};

    @Bean
    public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring()
                           .requestMatchers(allowedUrls)    // 일부 url 허용
                           .requestMatchers(PathRequest.toH2Console()); // h2 콘솔 사용을 위함
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
                .csrf(AbstractHttpConfigurer::disable)  // 쿠키 사용 안 함
                .authorizeHttpRequests(requests ->
                        requests.anyRequest().authenticated()   // 그 외 모든 요청은 인증 필요
                )
                .sessionManagement(sessionManagement ->
                        sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                )    // 세션을 사용하지 않으므로 STATELESS 설정
                .addFilterBefore(new JwtAuthenticateFilter(tokenProvider),
                        UsernamePasswordAuthenticationFilter.class)
                .build();
    }
}