정의
: 다른 출처에게 요청하는 것이 안전한지 판별하기 위해서 브라우저와 상호 통신하는 하나의 방법
즉, 웹 애플리케이션이 지금 실행중인 출처와 다른 출처의 자원에 접근할 수 있도록 권한을 부여하도록 브라우저에게 알려주는 체제
요약
: 출처 다른 애플리케이션에 아무나 접근하지 못하도록 방지하는 방어막. 허락해줘야지 리소스 쓸 수 있다.
같은 출처에서만 리소스를 공유할 수 있다
라는 정책
웹의 특성(누구나 쓸수있음)을 고려하여 예외 사항을 만듦
결론: 다른 출처로 리소스 요청하면 SOP 정책 위반함. 더해서, 예외 사항인 CORS 정책까지 안지키면 다른 출처 리소스 사용 불가! (CORS만 통과하면 쓸 수있다.)
출처
: Protocol + Host + 포트번호(있다면)
출처 비교
: 브라우저가 함
기본흐름
클라이언트: 다른(교차) 출처 리소스 요청시에는 HTTP 프로토콜을 사용해서 요청.
👇
브라우저
👇
서버
Access-Control-Allow-Origin
에 접근 허용된 출처 내려줌👇
브라우저
Access-Control-Allow-Origin
가 같은 지 비교그러나.... 실제 시나리오는 3개다.
- Preflight Request(프리플라이트)
- Simple Request
- Credentialed Request
Preflight Request
Preflight
)와 본 요청을 나누어 서버에 전송.예비요청: HTTP 메소드 중 OPTIONS
메소드 사용
실제 예시
네트워크 탭 열어서 확인가능
요청헤더
accept: */* accept-encoding: gzip, deflate, br accept-language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7 access-control-request-headers: content-type access-control-request-method: GET cache-control: no-cache origin: https://www.naver.com pragma: no-cache referer: https://www.naver.com/ sec-fetch-dest: empty sec-fetch-mode: cors sec-fetch-site: same-site user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36
access-control-request-headers: content-type
access-control-request-method: GET
origin: https://www.naver.com
이런 정보들을 다 보낸다.
응답헤더
access-control-allow-credentials: true access-control-allow-headers: content-type access-control-allow-methods: GET access-control-allow-origin: https://www.naver.com access-control-max-age: 1800 allow: GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH content-length: 0 date: Mon, 13 Jun 2022 05:52:51 GMT referrer-policy: unsafe-url server: nfront vary: Origin vary: Access-Control-Request-Method vary: Access-Control-Request-Headers
access-control-allow-origin: https://www.naver.com
보낸 출처와 같으니 잘 작동한다. 만약 달랐다면 cors 에러.
Simple Request
Access-Control-Allow-Origin
로 판단까다로운 조건...
1. 요청의 메소드는 GET, HEAD, POST 중 하나여야 한다.
2. Accept, Accept-Language, Content-Language, Content-Type, DPR, Downlink, Save-Data, Viewport-Width, Width를 제외한 헤더를 사용하면 안된다.
3. 만약 Content-Type를 사용하는 경우에는 application/x-www-form-urlencoded, multipart/form-data, text/plain만 허용된다.
Credentialed Request
옵션 종류
- same-origin(기본값): 같은 출처 간 요청에만 인증 정보를 담을 수 있다.
- include: 모든 요청에 인증 정보를 담을 수 있다.
- omit: 모든 요청에 인증 정보를 담지 않는다.
옵션에 따라서 브라우저가 cors 정책 검사를 더 엄격하게 한다.
사용예시
fetch('https://어쩌구 주소...', { credentials: 'include', });
이렇게 사용하면, 모든 요청에 쿠키랑 인증 등등 민감한 정보를 보내게 된다.
Access-Control-Allow-Origin
에*
같은 값 안된다. 또, 응답 헤더에는 반드시Access-Control-Allow-Credentials: true
가 존재해야한다
- 서버에서 Access-Control-Allow-Origin 세팅해주기 (
*
말고 url로 해주는게 적절하다.)- 프록시로 잠깐 브라우저 속이기
결론
: 어차피 해야할 설정. 처음부터 서버에서 해주는 게 제일 편하고 정석이다.