해당 포스트는 Spring Cloud에 속한 기술들에 대한 개념과 주요 기술에 대해 알아보고 실무에 적용했었던 내용을 정리하는 포스트입니다.
[이미지 출처 : https://www.carlosgonzalezgurrea.es/cabeceras-cors/]
CORS는 Cross-Origin Resource Sharing의 약자로, 웹 애플리케이션에서 발생하는 보안 상의 이슈를 해결하기 위한 표준 메커니즘입니다. 이는 웹 페이지의 스크립트가 다른 도메인의 자원에 접근할 수 있는 권한을 부여하는 메커니즘입니다.
CORS는 웹 브라우저에서 실행되는 스크립트가 동일한 출처(Origin)가 아닌 서버로부터 리소스를 요청할 때 발생합니다. 출처는 프로토콜, 호스트, 포트로 구성되며, 출처가 다를 경우 브라우저는 보안 상의 이유로 자원에 대한 접근을 허용하지 않습니다. CORS는 이러한 상황에서 서로 다른 출처 간에 안전하게 자원을 공유할 수 있도록 해주는 메커니즘입니다.
보안 강화 : 웹 보안을 강화하기 위해 브라우저가 제공하는 동일 출처 정책(Same Origin Policy)를 강화합니다. 이로써 악의적인 웹 사이트에서 사용자의 정보에 접근하는 것을 방지합니다.
사용자의 프라이버시 보호 : 브라우저는 동일 출처 정책을 통해 사용자의 개인 정보를 보호하고, 사용자가 방문하는 웹 사이트가 다른 출처에서의 자원 접근을 명시적으로 허용할 수 있도록 제어합니다.
CORS 허용을 하지 않을 경우 클라이언트와 API 게이트웨이, 그리고 마이크로서비스 간 통신이 불가능하므로 허용을 해줘야 하며 이 때 관련 설정은 API 게이트웨이와 마이크로서비스에서 처리를 합니다. (클라이언트 측에서도 가능은 하지만 리버스 프록시 등이 필요)
Spring Cloud Gateway에서는 기본적으로 CORS 설정 옵션을 가지고 있습니다. 예시는 다음과 같습니다.
spring:
cloud:
default-filters:
- DedupeResponseHeader=Access-Control-Allow-Origin Access-Control-Allow-Credentials
globalcors:
cors-configurations:
'[/**]':
allowedOrigins:
- 'http://localhost:5173' # 허용하려는 도메인
allow-credentials: true # 요청 시 인증 정보를 전송하도록 허가
allowedHeaders: '*' # 허용하려는 헤더
allowedMethods: # 허용하려는 HTTP 메서드
- PUT
- GET
- POST
- DELETE
- OPTIONS
spring.cloud.globalcors.cors-configurations
설정으로 CORS에 필요한 설정을 지정할 수 있습니다.
여기서 default-filters에 있는 DedupeResponseHeader의 경우 응답 시 중복 헤더를 삭제해주는 필터인데, globalcors에서 allow-credentials를 설정할 경우 CORS 필터가 추가되어 해당 헤더를 응답에 포함시키는데 이전 응답에 이와 관련된 헤더가 존재할 경우 중복될 수 있으므로 중복 헤더를 방지하기 위해 처리합니다.
물론 위의 DedupeResponseHeader 필터는 필수 설정은 아닙니다. 게이트웨이와 마이크로서비스의 CORS 설정을 따로
가져갈 일이 없다면 위의 필터를 빼고 게이트웨이의 CORS 설정을 전역적으로 적용하면 됩니다.
위에서처럼 DedupeResponseHeader 필터를 설정했을 경우 API 게이트웨이 뿐만 아니라 마이크로서비스에서도 CORS 설정을 해줘야 합니다. 이는 Spring Security를 통해 처리할 수 있습니다.
@Configuration
public class SecurityConfig {
// 기타 설정들...
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// 기타 필터 체인 관련 설정들...
http.cors().configurationSource(corsConfigurationSource());
return http.build();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Arrays.asList("http://localhost:5173"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"));
configuration.addAllowedHeader("*");
configuration.addAllowedOriginPattern("*");
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
https://cloud.spring.io/spring-cloud-gateway/reference/html/#cors-configuration
해당 설정은 마이크로서비스 인스턴스의 cors 설정과 API Gateway의 cors 설정 중복으로 브라우저에서 cors 에러가 뜨지 않나요? 마이크로서비스 인스턴스와 API Gateway 간에서의 cors 설정을 하신 건 아닌 것 같은데, 클라이언트와의 도메인 출처 불일치로 인한 차단을 극복하기 위해서 API Gateway에서 cors 설정을 하는 것으로 알고 있는데 해당 방법으로 클라이언트에서 정상적인 응답 처리가 이뤄지나요?