CORS error 발생! 그게 뭔데?
이전에 잘만 서버에서 처리하던 업로드 요청이...
도메인을 구입하여 서버와 연결한 이후에
파일 업로드 기능을 수행했더니 ... 다음과 같은 상황이 발생했다.
빨간색으로 에러가 팡팡~ 서버에서 처리하지 못하는 에러는 아니다.
CORS error, preflight 그게 뭔데~~!
OPTIONS 메서드는 뭔데~~!
출처에 따른 리소스 공유
브라우저는 SOP(Standard Operating Procedures) 정책을 따른다.
그 정책중에 "같은 출처에서만 리소스를 공유할 수 있다"가 있다.
출처에 따른 리소스 공유가 무엇일까?
내가 만든 웹이 a.com이라고하자.
a.com에서 업로드된 이미지 파일을 가져오기위해서 a.com에 이미지 파일을 요청할 수 있다.
이때 a.com에서 a.com으로 요청을 했다. 이것이 같은 출처에게 리소스를 공유하는 상황이다.
내가 만든 웹이 a.com인데
이 웹에서 이미지 파일을 가져오기위해 b.com에 요청할 수 있다.
이때 a.com에서 b.com으로 요청했다. 다른 출처를 가지는 리소스를 공유하는 상황이다.
이것은 기본 COP 정책을 위반하는것이다.
CORS ?
CORS는 Cross-Origin Resource Sharing이다.
"교차 출처 리소스 공유" 다른 출처끼리 리소스를 공유하는 것이다.
클라이언트 애플리케이션은 공격을 받기도 하기도 쉬운 환경이기 때문에 CORS 정책이 필요한 것이다.
OPTIONS, Preflight ?
CORS 시나리오에는 Simple Request, Preflight Request, Credential Request 3가지가 존재한다.
Simple Request는 특정 조건을 만족하는 경우
서로 다른 출처라도 CORS 정책 검사를 하지 않고, 예비 요청을 생략할 수 있는 경우이다.
현재 내가 발생한 문제는 Preflight Request에서 발생한 문제라서 이 경우만 다뤄보자.
Preflight Request 경우에 한번에 본 요청을 보내지 않고, 예비 요청을 먼저 보낸다.
이 예비 요청을 Preflight라고 부르며 OPTIONS 메서드를 사용한다.
예비 요청을 통해서 브라우저가 이 요청을 보내는것이 안전한지 확인하는 단계이다.
HOST와 Origin
http://13.123.123.12:8080/posters/image
"http://"는 Protocol
"13.123.123.12:8080"는 Host
"/posters/image"는 path이다.
Host는 내가 요청을 보내는 대상이고,
Origin은 요청이 시작하는곳이 된다. 위의 표현에서 "내가"되는것이다.
문제 원인 및 해결 방법
서버에 이미지 파일을 보내는 자바 스크립트 코드의 일부분이다.
const xhr = this.xhr = new XMLHttpRequest();
xhr.open('POST', 'http://13.123.123.12:8080/posters/image', true);
URL이 "http://13.123.123.12:8080/"으로 요청을 보내는 대상인 HOST가 "13.123.123.12:8080"으로 되어있다.
웹 브라우저는 기본적으로 같은 출처의 리소스만 허용하기 때문에
도메인을 등록한 이후 a.com으로 접속했기 때문에 요청이 시작하는 출처인 Origin이 a.com인데
요청을 보내는 대상인 HOST가 "13.123.123.12:8080"이기 때문에
달라서 CORS 에러가 발생하는 것이다.
즉, HOST는 13.123.123.12:8080인데 Origindms a.com이라 CORS 발생한것이다.
만약 다른곳에서 API를 사용하지 않는 상황이고 자신의 사이트에서만 사용한다면
간단하게 다음과 같이 HOST를 Origin으로 맞춰주면 에러는 해결할 수 있다.
만약 세세하게 Cors 정책을 설정하고싶다면 다음과 같이 CorsFilter를 빈으로 등록해주자.
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true); // 내 서버가 응답할때 json을 자바스크립트에서 처리할 수 있게 할지를 설정하는 것 (ajax와 같은걸로 요청했을때 응답을 처리할 수 있게 해줄까말까)
config.addAllowedOrigin("*"); // 모든 IP에 응답 허용
config.addAllowedHeader("*"); // 모든 헤더에 응답 허용
config.addAllowedMethod("*"); // 모든 post, get, put, delete 등등 요청을 허용하겠다.
source.registerCorsConfiguration("/**", config);
CorsFilter corsFilter = new CorsFilter(source);
return corsFilter;
}
}