흔히 말하는 CORS 에러는 개발하면서 한번쯤은 만나는 에러이고, 프로젝트를 진행하면서 많이 만났었다. 또한 CORS는 SOP로 인해 파생된 개념이다.
웹 브라우저의 보안 정책 중 하나로, 브라우저가 같은 출처의 리소스만 허용하도록 하는 정책이다.
same-origin은 다음 세 가지 요소가 모두 일치해야 한다.
protocol
host (도메인 이름)
port
http://example.com:80/page1
http://example.com:80/page2
http://example.com
https://example.com
SOP는 악의적인 웹 페이지가 다른 사이트의 중요한 정보에 무단 접근하지 못하도록 막기 위한 보안 장치이다. 예를 들어, 사용자가 로그인한 상태의 사이트 정보를 다른 출처의 사이트가 js로 훔쳐보는 것을 막아준다.
교차 삽입
: 다른 origin의 자원을 태그로 불러오는 것.
다음과 같은 교차 삽입 동작은 SOP에 상관없이 허용된다.
<link>
태그로 다른 도메인의 CSS 가져오기<script>
태그로 다른 도메인의 JS 가져오기<img>, <video>, <audio>, <embed>, <object>
<iframe>
으로 삽입되는 모든 것CSS
간단히, 다른 출처 간에 리소스 공유를 허용하도록 하는 정책이다.
프론트-백엔드 간 원활한 협업을 위해서는 SOP와 CORS에 대한 이해가 꼭 필요하다.
이전에 만났던 CORS 에러에 대해 정리했던 글이 있다.
XMLHttpRequest
, Fetch 호출브라우저는 OPTIONS 메서드를 통해 preflight request를 보낸다.
서버는 이 요청에 대해 허용할 범위를 response header에 포함시켜 응답한다 (Access-Control-Allow-Origin 등)
클라이언트가 보내려는 요청이 허용된 요청일 경우에만 본 요청을 보내고, 그렇지 않으면 에러를 발생시킨다.
CORS 요청(다른 origin에 자원을 요청)은 브라우저에 요청을 보낼 때 preflight 요청(사전 요청)을 먼저 보낸다. 이는 서버에 해당 요청에 대한 허가 여부를 확인하는 것이다.
preflight 요청은 OPTIONS 메서드
로 요청하며, 서버에 다음과 같은 정보들을 보낸다.
OPTIONS /api/data HTTP/1.1
Host: api.example.com
Origin: https://front.example.com
Access-Control-Request-Method: POST #실제 요청의 메서드
Access-Control-Request-Headers: Content-Type, Authorization #실제 요청의 추가 헤더
Origin
- 요청 서버의 origin
Access-Control-Request-Method
- 실제 요청에서 어떤 메서드를 사용할 것인지 서버에게 알린다
Access-Control-Request-Headers
- 실제 요청에서 어떤 header를 사용할 것인지 서버에게 알린다
이후 이 요청을 받는 서버는 해당 요청에 대해 허용하는 값들을 응답에 넣어 반환한다.
HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://front.example.com #허용 출처(domain)
Access-Control-Allow-Methods: POST, GET, OPTIONS #허용 메서드
Access-Control-Allow-Headers: Content-Type, Authorization #허용 헤더
Access-Control-Max-Age: 3600 #Prefilght 응답 캐시 기간
브라우저는 요청과 응답을 비교해서 CORS 정책에 부합하는지 확인
한다. 부합한다면 실제 요청을 보내고, 아니라면 본 요청을 보내지 않고 CORS 에러를 발생시킨다.