최근 프로젝트에서 "Invalid CORS request"와 함께 403 Forbidden 에러를 마주하게 되었습니다. CORS 설정은 이미 WebMvcConfigurer
를 통해 모든 도메인과 모든 요청을 허용해 두었는데, 예상과 달리 브라우저에서 CORS 오류가 발생했습니다. 이 문제를 해결하는 과정에서 Spring Security 6.1의 변화와 CORS 설정 방식을 새롭게 이해할 수 있었습니다. 이 글에서는 문제 상황과 해결 과정을 정리해보겠습니다.
프로젝트 환경은 Spring Boot와 Spring Security를 사용 중이었고, 다음과 같은 CorsConfig
를 사용하여 모든 도메인에서의 요청을 허용한 상태였습니다.
@Configuration
public class CorsConfig {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*") // 모든 도메인 허용
.allowedMethods("*") // 모든 HTTP 메소드 허용
.allowedHeaders("*") // 모든 헤더 허용
.allowCredentials(true); // 자격 증명 허용
}
};
}
}
Spring Security 설정 역시 다음과 같이 되어 있었는데, 모든 요청을 허용하는 개발 단계의 설정이었습니다.
http
.cors() // CORS 설정 활성화
.csrf().disable()
.authorizeHttpRequests(authorize -> authorize
.anyRequest().permitAll() // 모든 요청을 허용
);
그런데도 불구하고 CORS 오류가 발생하면서, 브라우저 콘솔에는 "Invalid CORS request"와 403 Forbidden 오류가 떴습니다.
문제를 조사하던 중, Spring Security 6.1부터 http.cors()
메서드가 Deprecated 되었고, 곧 제거될 예정이라는 사실을 발견했습니다.
cors()
is deprecated since version 6.1 and marked for removal
이는 Spring Security의 CORS 설정 방식이 변경되었음을 의미했습니다. 기존 방식으로는 더 이상 CORS 설정이 제대로 동작하지 않으며, Spring Security가 WebMvcConfigurer
에서 정의한 CORS 설정을 무시할 가능성이 있다는 것이었습니다.
문제를 해결하기 위해 CorsConfigurationSource
를 명시적으로 정의하고, 이를 Spring Security에 연결하는 새로운 방식으로 설정을 변경해야 했습니다.
먼저, CORS 규칙을 정의하는 CorsConfigurationSource
를 Bean으로 등록했습니다. 이를 통해 Spring Security가 사용할 CORS 규칙을 명확히 설정할 수 있습니다.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.cors.CorsConfigurationSource;
import java.util.List;
@Configuration
public class CorsConfig {
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOriginPatterns(List.of("*")); // 모든 도메인 허용
configuration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE")); // 모든 메소드 허용
configuration.setAllowedHeaders(List.of("*")); // 모든 헤더 허용
configuration.setAllowCredentials(true); // 자격 증명 허용
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration); // 모든 경로에 대해 적용
return source;
}
}
다음으로, Spring Security 설정에서 deprecated된 cors()
대신, CorsConfigurationSource
를 명시적으로 사용하여 CORS 설정을 적용했습니다.
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.cors.CorsConfigurationSource;
@Configuration
public class SecurityConfig {
private final CorsConfigurationSource corsConfigurationSource;
public SecurityConfig(CorsConfigurationSource corsConfigurationSource) {
this.corsConfigurationSource = corsConfigurationSource;
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.cors(cors -> cors.configurationSource(corsConfigurationSource)) // 새로운 방식으로 CORS 설정 적용
.csrf().disable() // 필요에 따라 CSRF 비활성화
.authorizeHttpRequests(authorize -> authorize
.anyRequest().permitAll() // 모든 요청을 허용 (개발 단계)
);
return http.build();
}
}
이제 CorsConfigurationSource
를 통해 CORS 규칙이 명확히 설정되고, Spring Security는 해당 규칙을 기반으로 요청을 처리합니다.
Spring Security 6.1부터는 CORS 설정 방식이 변경되면서, 기존의 http.cors()
방식으로는 더 이상 CORS 문제를 해결할 수 없습니다. 대신, CorsConfigurationSource
를 사용하여 CORS 규칙을 명시적으로 정의하고, 이를 Spring Security 설정에 적용해야 합니다.
이 방법을 적용한 후에는 더 이상 "Invalid CORS request"나 403 오류가 발생하지 않았습니다. 만약 여러분도 Spring Security 6.1 이후 CORS 문제를 겪고 있다면, 이와 같은 방식으로 설정을 수정해보세요. 최신 버전에 맞게 코드를 업데이트함으로써 문제를 해결할 수 있습니다.
참고