Development Logs/Spring Ecosystem

[Spring GW] Spring Cloud GW에서 CORS 정책 적용

유뱅유뱅뱅 2025. 2. 23. 22:07
반응형

CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present

  • CORS는 브라우저가 서버로 요청을 보낼 때 특정 HTTP 헤더를 추가하여 서버가 요청을 허용할지 결정하는 방식으로 동작합니다. 크게 단순 요청(Simple Request)과 사전 요청(Preflight Request) 두 가지가 있습니다.
  • 이 중 사전 요청을 하는 과정에서 CORS 이슈가 발생하여, 이를 해결해가던 과정을 작성하였습니다.

1. CORS 란?

CORS (Cross-Origin Resource Sharing)는 웹 브라우저에서 실행되는 스크립트가 다른 출처(도메인, 프로토콜, 포트)에 있는 리소스를 요청할 수 있도록 허용하는 보안 정책이입니다. 기본적으로 웹 브라우저는 보안상의 이유로 동일 출처 정책(Same-Origin Policy, SOP)을 적용하는데, CORS는 이를 확장하는 역할을 해줍니다.

 

2. CORS 관련 이슈 확인

2.1. 브라우저 콘솔에 찍힌 내용

CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present

2.2. Response Header 분석

content-length: 0
date: Thu, 02 Jan 2025 08:38:43 GMT
status: 403
vary: Origin
vary: Access-Control-Request-Method
vary: Access-Control-Request-Headers

1) 403 상태 코드

  • 403 Forbidden은 서버가 요청을 이해했지만 이를 승인하지 않는다는 의미입니다.
  • 이 경우는 CORS에 걸린 가능성이 높습니다.

2) Vary 헤더

  • Vary 헤더는 서버가 응답 캐싱을 제어하기 위해 사용하는 HTTP 헤더입니다.
  • 이 헤더는 응답이 요청 헤더에 따라 달라질 수 있음을 나타냅니다.
  • 예: Vary: Origin이 포함된 응답은 요청의 Origin 헤더 값에 따라 응답이 달라질 수 있음을 나타냅니다. 따라서, 캐시 저장소는 각 Origin 헤더 값에 대해 별도의 응답을 캐싱합니다.

3) 해당 응답에서 의미

  • Vary: Origin: 서버는 요청의 Origin 헤더를 확인하고 이에 따라 다른 응답을 반환할 수 있음을 나타냅니다.
  • Vary: Access-Control-Request-Method: 요청의 Access-Control-Request-Method에 따라 응답이 달라질 수 있음을 나타냅니다.
  • Vary: Access-Control-Request-Headers: 요청의 Access-Control-Request-Headers 값에 따라 응답이 달라질 수 있음을 나타냅니다.

4) 응답이 CORS에 걸린 이유

Preflight 요청 처리 실패:

  • 브라우저가 보낸 OPTIONS 요청(Preflight 요청)에 대해 서버가 적절한 Access-Control-* 응답 헤더를 반환하지 않았을 가능성이 높습니다.
  • 예를 들어, 요청에서 사용한 Origin, Access-Control-Request-Method, 또는 Access-Control-Request-Headers 값이 허용되지 않은 경우.

403 응답:

  • 서버가 CORS 설정에서 특정 요청을 허용하지 않도록 제한했을 가능성이 있습니다.
  • 서버는 요청을 차단했으며 브라우저는 이를 CORS 오류로 간주할 수 있습니다.

 

3. Spring Cloud GW에서 CORS 정책 적용

  • 우리의 서비스는 Client와 Provider 서버 의 인터페이스 역할을 수행하고 있는 서비스 이므로, Provider 서버의 CORS 정책을 따라야된다고 판단하여, GW에서는 모두 허용하도록 하였습니다.
    • Migration하고 있는 기존 IBM APIM GW Solution의 CORS 정책을 알 수 없는 이유도 존재하였습니다.
@Configuration
public class CorsConfig {

    @Bean
    CorsWebFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowedOrigins(List.of(CorsConfiguration.ALL));
        config.setAllowedHeaders(List.of(CorsConfiguration.ALL));
        config.setAllowedMethods(List.of(CorsConfiguration.ALL));

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);

        return new CorsWebFilter(source);
    }
}
  • 위의 코드처럼 CorsWebFilter를 활용하여, 모든 요청에 대해 CORS를 적용하였습니다.
  • Origin, Headers, Methods를 다 허용하도록 하였습니다.

 

참고. CORS 응답 헤더 설명

  • Access-Control-Allow-Origin 허용할 도메인 지정 (*은 모든 도메인 허용)
  • Access-Control-Allow-Methods 허용할 HTTP 메서드 지정 (GET, POST, PUT, DELETE, OPTIONS)
  • Access-Control-Allow-Headers 클라이언트가 보낼 수 있는 요청 헤더 지정
  • Access-Control-Expose-Headers 클라이언트가 접근할 수 있는 응답 헤더 지정
  • Access-Control-Allow-Credentials true인 경우, 브라우저는 쿠키 또는 인증 정보 포함 가능
  • Access-Control-Max-Age Preflight 요청 결과를 캐싱하는 시간 (초 단위)

 

반응형