SOP? CORS?
CORS는 추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제
왜 CORS가 필요한가?
cors는 악의적인 해커로부터 브라우저를 지키기 위해 만들어졌다
이전에 사용자가 홈페이지에 로그인을 하여 쿠키에 토큰 정보가 남을 경우 악의적인 해커가 사용자에게 해당 홈페이지를 흉내낸 가짜 홈페이지를 보내 그 사용자가 가짜 홈페이지를 들어가게 되면 쿠키에 있는 토큰 정보를 탈취하게 되고, 악성해커가 진짜 홈페이지에 사용자의 토큰으로 로그인을 하여 정보를 빼올 수 있었다.
그 해당 쿠키를 빼오는 방법은 아래와 같다.
이전엔 다른 출처에 리소스를 요청할 때,
fetch('http://another.com', {
credentials: "include"
});
이런식으로 요청을 기본적으로 하게 되어 해당 도메인의 쿠키까지 다 가져올 수 있었다.
하지만 아까 말한 악성 해킹을 막기위해 SOP라는 same origin policy가 생겼고
fetch 요청을 해도 같은 도메인이 아니면 도메인의 정보를 주지 않게 되었다.
하지만 개발자들이 교차출처 리소스가 필요해지자, CORS가 생겨나게 되었고, fetch에 credentials라는 옵션을 주지 않으면 쿠키가 함께 전송되지 않고, 크로스 오리진 요청을 보내게 되고, credentials: include 요청을 보내게 되면 쿠키값과 함께 크로스오리진 요청을 보낼 수 있게 되었다
fetch('http://another.com', {
credentials: "include"
});
브라우저는 안전하지 않은 요청을 어떻게 판별할 수 있을까
브라우저가 안전하지 않다고 여긴 요청일 경우 preflight 요청(예비 요청)을 하게 되고, 안전하다고 여긴 요청일 경우 simple request를 보내게 된다.
안전하지 않은 요청으로 분류되는 경우
- PATCH 메서드를 사용하고 있습니다.
- Content-Type이 application/x-www-form-urlencoded나 multipart/form-data, text/plain가 아닙니다.
- 비표준 헤더 API-Key를 사용합니다.
서버에서 200코드와 함께
- Access-Control-Allow-Methods: PATCH
- Access-Control-Allow-Headers: Content-Type,API-Key
이 코드를 보내 안전한 요청이라고 응답을 보내면 본요청을 보내게 된다
본 요청은 크로스 오리진 요청이기에 Origin 헤더가 붙게 된다.
서버에서 본 응답에 Access-Control-Allow-Origin 헤더를 반드시 붙여줘야 한다.
이 과정이 끝나야 안전하지 않은 요청이 성공적으로 응답하면 실제 응답을 읽을 수 있다
안전한 요청으로 분류되는 경우
- 메서드: GET이나 POST 혹은 HEAD
- 헤더:
- Accept
- Accept-Language
- Content-Language
- 값이 application/x-www-form-urlencoded나 multipart/form-data, text/plain인 Content-Type
절차
- → 오리진 정보가 담긴 Origin 헤더와 함께 브라우저가 요청을 보냅니다.
- ← 자격 증명이 없는 요청의 경우(기본), 서버는 아래와 같은 응답을 보냅니다.
- Origin 값과 동일하거나 *인 Access-Control-Allow-Origin
- ← 자격 증명이 있는 요청의 경우 서버는 아래와 같은 응답을 보냅니다.
- Origin 값과 동일한 Access-Control-Allow-Origin
- 값이 true인 Access-Control-Allow-Credentials
출처