웹 개발을 하다보면 우리가 가져오는 리소스들이 안전한지 검사하게 되는 정책과 마주하게 되는데, SOP(Same Origin Policy)와 CORS(Cross Origin Resource Sharing)가 있다.
이는 서버에 구현된 스펙이 아닌 브라우저에 구현된 스펙이다. 서버는 정책 위반 여부에 관여하지 않는다. 서버가 요청에 응답하고, 응답이 브라우저에 도착하면 브라우저가 그 응답을 분석해 정책 위반 여부를 검사하게 된다. 그래서 서버에서 정상적으로 응답(200 OK)을 하더라도, 정책에 위반되면 브라우저는 그 응답을 처리하지 않고 버리게 된다.
URL은 위의 사진과 같이 구성되어 있는데, 그 중에서 Protocol, Host, Port를 합쳐 Origin이라고 한다.
Origin(Protocol, Host, Port)이 일치하면 SOP, 일치하지 않으면 CORS를 따른다.
“같은 출처에서만 리소스를 공유할 수 있다” 라는 규칙을 가진 정책이다. 즉 Origin (Protocol, Host, Port)가 동일한지 확인하면 된다. Origin이 같다면 나머지 요소는 다르더라도 같은 출처로 인정된다.
자바 스크립트는 서로 다른 도메인(호스트)에 대한 요청을 보안상 제한하기에, XMLHttpRequest, Fetch API 등 script 태그 내에서는 기본적으로 SOP를 따른다.
✔️ “ https://github.com/about “ 를 기준으로 Same Origin인지 비교해보자.
추가 HTTP 헤더를 사용해, 한 Origin에서 실행 중인 웹 애플리케이션이 다른 Origin의 선택한 Resource에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제이다. 웹 애플리케이션은 Resource가 자신의 Origin과 다를 때 Cross Origin HTTP 요청을 실행한다.
HTML은 기본적으로 CORS를 따른다. link 태그에서 다른 Origin의 CSS 등의 리소스에 접근하거나, img 태그에서 다른 리소스에 접근하는 것이 가능한 이유이다.
자바 스크립트의 fetch API를 통해 브라우저에게 리소스를 받아오려는 상황
1. 브라우저가 서버로 예비 요청을 보냄
2. 서버는 정책 정보를 담아서 브라우저로 응답
3. 브라우저는 자신이 보낸 예비 요청과 서버가 응답해준 정책을 비교해 해당 요청이 안전한지 확인 후, 서버에 본 요청을 다시 보냄
4. 서버가 본 요청에 대해 응답하면 최종적으로 이 응답 데이터를 자바 스크립트로 넘겨줌
요청 Method는
GET, HEAD, POST 중 하나여야 한다.
Content-Type은
application/x-www-form-urlencoded, multipart/form-data, text/plain 중 하나여야 한다.
유저 에이전트가 자동으로 설정한 헤더 외에, 수동으로 설정할 수 있는 헤더는 Fetch 명세에 “CORS-safelisted request-header”로 정의한 헤더만 사용할 수 있다.
예시)
1. 클라이언트는 HTTP 요청 헤더에 Origin을 담아 서버로 전달
2. 서버는 응답 헤더에 Access-Control-Allow-Origin을 담아 클라이언트로 전달
3. 클라이언트에서는 서버와 주고 받은 Origin과 Access-Control-Allow-Origin을 비교해 정책 위반 여부 확인
same-origin: (기본값) 같은 출처 간 요청에만 인증 정보를 담을 수 있음
include: 모든 요청에 인증 정보를 담을 수 있음
omit: 모든 요청에 인증 정보를 담지 않음
예시)
// Fetch Credential
fetch('URL', {
method: 'PUT',
credentials: 'include'
});
// Axios withCredentials
export function createInstance() {
const instance = axios.create({
withCredentials: true,
});
return setInterceptors(instance);
};
만약, 이러한 옵션을 사용해 리소스 요청에 인증 정보가 포함되면, 브라우저는 정책 위반 여부를 검사할 때, Access-Control-Allow-Origin뿐만 아니라 다른 조건 2가지을 추가해 검사한다.