CORS(Cross-Origin Resource Sharing, 교차 출처 리소스 공유)
- HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제로 웹 애플리케이션이 리소스가 자신의 출처와 다를 때 브라우저는 요청 헤더에 Origin 필드에 요청 출처를 함께 담아 교차 출처 HTTP 요청을 실행함.
- CORS는 브라우저에 구현된 스펙으로, 브라우저가 클라이언트의 요청 헤더와 서버의 응답헤더를 비교해서 최종 응답을 결정한다.
- 두 개의 출처를 비교하는 방법은 URL 구성요소 중에서 Protocol, Host, Port 세 가지가 모두 동일한 지 판단
CORS의 종류
1. Simple Request
- 예비 요청(Preflight) 과정 없이 바로 서버에 본 요청을 한 후, 서버가 응답의 헤더에 Access-Control-Allow-Origin과 같은 값을 전송하면 브라우저가 서로 비교 후 CORS 정책 위반여부를 검사하는 방식.
- 조건1. GET, POST, HEAD 중의 한 가지 메서드를 사용해야 함
- 조건2. 헤더는 Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width Width만 가능하고 나머지는 허용 X
- 조건3. Content-Type은 application/x-www-form-urlencoded, multipart/form-data, text/plain 만 가능
위의 세 가지 제약사항을 모두 만족하면 Simple Request가 가능.
2. Preflight Request (예비 요청)
- 브라우저는 요청을 한 번에 보내지 않고 예비 요청과 본 요청을 나누어서 전달함. 이 때 보내는 예비 요청을 Preflight라고 하며 예비 요청의 HTTP Method는 OPTIONS가 사용
- 본 요청을 보내기 전에 브라우저 스스로 안전한 요청인지 확인하는 것으로 요청 사양이 Simple Request에 해당하지 않을 경우 Preflight Request를 실행
동일 출처 판단 기준
URL (서버 URL이 “https://security.com” 이라고 가정) | 동일 출처 | 근거 |
https://security.com/auth?username=userA | O | 프로토콜, 호스트, 포트(https 443) 동일 |
https://user:password@security.com | O | 프로토콜, 호스트, 포트 동일 |
http://security.com | X | 프로토콜이 다름 |
https://app.security.com | X | 호스트가 다름 |
https://security.com:8000 | ? | 브라우저에 따라 다름 |
CORS를 해결하려면?
서버에서 Access-Control-Allow-* 를 세팅해주어야 한다.
- Access-Control-Allow-Origin :
- 헤더에 작성된 출처만 브라우저가 리소스를 접근할 수 있도록 허용
- *, “https://security.com”
- Access-Control-Allow-Methods :
- preflight request에 대한 응답으로 실제 요청 중에 사용할 수 있는 헤더 필드 이름을 나타냄
- 기본값은 GET, POST, HEAD, OPTIONS, *
- Access-Control-Allow-Headers :
- preflight request에 대한 응답으로 실제 요청 중에 사용할 수 있는 헤더 필드 이름을 나타냄
- 기본값은 Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers, Custom Header, *
- Access-Control-Allow-Credentials :
- 실제 요청에 쿠키나 인증 등의 사용자 자격 증명이 포함될 수 있음을 나타냄. Client의 credentials:include 일 경우 true 필수
- Access-Control-Allow-Age :
- preflight 요청 결과를 캐시 할 수 있는 시간을 나타내는 것으로 해당 시간동안은 preflight 요청을 다시 하지 않음
스프링 시큐리티에서 CORS 처리
- CorsConfigurer :
- 필터 체인에 CorsFilter를 추가
- corsFilter 라는 이름의 빈이 있다면 해당 CorsFilter 사용, 위 빈이 없고 CorsConfigurationSource 빈이 정의되었다면 해당 CorsConfiguration이 사용
- CorsConfigurationSource 빈이 정의되어 있지 않은 경우 Spring MVC가 클래스 경로에 있으면 HandlerMappingIntrospector 가 사용
- CorsFilter
- CORS 예비 요청을 처리하고 CORS 단순 및 본 요청을 가로채고, 제공된 CorsConfigurationSource를 통해 일치된 정책에 따라 CORS 응답 헤더와 같은 응답을 업데이트하기 위한 필터
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.cors(corsConfigurer -> corsConfigurer.configurationSource(apiConfigurationSource()));
...
}
@Bean
CorsConfigurationSource apiConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(Collections.singletonList("http://localhost:5173"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
configuration.setAllowedHeaders(Collections.singletonList("*"));
configuration.setAllowCredentials(true);
configuration.setMaxAge(3600L);
configuration.setExposedHeaders(Collections.singletonList("Set-Cookie")); // JWT 토큰이라면 Authentication
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration); // 서비스의 모든 경로에 대해서 판단
return source;
}
참고 : 위 코드에서 configuration.setAllowCredentials(true); 로 설정할 시 AllowedOrigin에 파라미터 와일드카드(*) 사용 불가능
'CS' 카테고리의 다른 글
OAuth2.0 개념 (1) | 2025.01.02 |
---|---|
HTTP의 이해 (0) | 2024.12.27 |
프로세스와 스레드 (1) | 2024.12.26 |
웹 서버, WAS, 리버스 프록시 (0) | 2024.12.26 |
쿠키, 세션, 토큰 (0) | 2024.12.26 |