Same-Origin Policy와 CORS

JunSeok·2024년 5월 21일
1

지식 기록

목록 보기
7/14

Same-Origin Policy(동일 출처 정책)

Same-Origin Policy는 웹 보안 메커니즘 중 하나로 실행중인 애플리케이션의 출처와 다른 출처의 리소스를 요청하는 것을 제한하는 정책이다.

브라우저는 Same-Origin Policy(동일 출처 정책)에 따라 실행중인 애플리케이션의 출처와 다른 출처의 리소스를 요청하면 차단한다.
여기서 말하는 출처는 프로토콜, 호스트, 포트 번호를 말하며, 이 세 가지 요소가 모두 동일한 경우 두 리소스가 동일한 출처를 가지고 있다고 판단한다.

XMLHTTPRequest, Fetch API, 쿠키, 로컬 스토리지 등과 같은 웹 API에 적용된다.

하지만 서로 다른 출처를 아예 차단해버리는 SOP(Same-Origin Policy)를 곧이 곧대로 따르면 상당히 불편할 수 있다.

출처가 서로 다른 요청도 가능하게 하면서 보안상의 문제도 해결하기 위해서 등장한 것이 바로 CORS이다.

CORS

CORS는 Cross Origin Resource Sharing의 약자이며, 교차 출처 리소스 공유를 의미한다.

동작 흐름

  1. 브라우저는 다른 출처의 리소스를 요청할 때 Origin 헤더에 요청 출처를 기록한다.
  2. 서버는 Access-Control-Allow-Origin 헤더에 허용할 출처를 기록하여 응답 헤더에 담아 보낸다.
  3. 브라우저는 Origin 의 출처와 Access-Control-Allow-Origin 헤더의 출처를 비교하여 동일하지 않은 출처로 판단하면 CORS 에러를 발생시킨다.

여기서 중요한 점은 서버가 응답값과 상태코드 200을 보내도, 브라우저가 CORS 위반 사실을 확인하면 애써 받은 응답값을 버린다는 점이다.
(대부분의 요청은 사전 요청 방식(preflight)으로 이루어져, 실제 요청이 이루어지기 전 CORS 위반 에러를 만날 수 있다.)

즉 에러 발생 주체는 서버가 아니라 브라우저라는 사실을 알아야 한다.

요청 종류

단순 요청

아래 조건을 충족하는 단순 요청은 사전 요청을 트리거하지 않는다.
하지만 대부분의 경우 조건을 충족하지 못하고 사전 요청을 한다.

  • GET, POST, HEAD 메서드 중에 하나 사용
  • 자동 설정 헤더를 제외하고 아래의 헤더값만 수동으로 설정된 것
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type(헤더 값이 아래 값 중 하나일 때)
      - application/x-www-form-urlencoded
      - multipart/form-data
      - text-plain

사전 요청(preflight)

사전 요청이란 실제 요청을 보내기 전, 해당 출처 리소스에 접근 권한이 있는지 브라우저와 서버가 서로 확인하기 위한 요청을 의미한다.
사전 요청은 일반적인 상황에서는 브라우저에서 자동으로 발생한다.

흐름

  1. 브라우저에서 서버로 예비 요청 전송
  • 브라우저는 OPTIONS 메서드로 요청을 보낸다.
  • Origin에 요청 출처를 기입한다.
  • 지원하고자 하는 메서드는 Access-control-Request-Method 헤더에 기입한다.
  • 사용자 정의 헤더를 설정했을 경우 Access-Control-Request-Headers 헤더에 기입한다.
  1. 서버는 어떤 것을 허용하고 금지하는지 헤더에 담아서 응답한다.
  • Access-Control-Allow-Origin 헤더에 허용 출처를 기입한다.
  • Access-Control-Allow-Methods 헤더에 허용 메서드를 기입한다.
  • Access-Control-Allow-Headers 헤더에 허용 헤더를 기입한다.

캐시

매번 사전 요청을 보내는 것은 본 요청만 보내는 단순 요청에 비해 네트워크 비용이 더 크다.
이를 해결 하기 위해 서버의 승인 하에 브라우저가 사전 요청을 생략할 수 있다.
서버는 Access-Control-Max-Age 헤더에 초단위로 캐시 사용 기한을 설정할 수 있다.

자격 증명 포함 요청

기본적으로 브라우저는 보안상의 이유로 교차 출처 요청에 자격 증명을 포함하지 않는다.
여기서 말하는 자격 증명은 쿠키 또는 Authorization 헤더를 의미한다.
이를 가능하게 하기 위해서 프론트와 서버 양측에서 CORS를 설정해야 한다.

프론트

Fetch API를 사용할 경우 credentials 옵션을 설정한다.

  • same-origin(기본값): 같은 출처 사이에만 인증 정보를 담는다.
  • include: 모든 요청에 인증 정보를 담는다.
  • omit: 모든 요청에 인증 정보를 담지 않는다.

Axios를 사용할 경우 withCredentials 옵션을 설정한다.

  • 기본값은 false이다.
  • 자격 증명 요청을 위해서 값을 true로 설정한다.

서버

  1. 응답 헤더에 Access-Control-Allow-Credentials : true 를 추가한다.
  2. 응답 헤더의 Access-Control-Allow-Origin 을 정확하게 설정한다. 즉, 와일드카드(*)를 사용하지 않는다.
  3. 응답 헤더의 Access-Control-Allow-Methods의 값을 지정해야 할 경우 와일드카드 문자(*)는 사용할 수 없다.
  4. 응답 헤더의 Access-Control-Allow-Headers의 값을 지정해야 할 경우 와일드카드 문자*)를 는 사용할 수 없다.

예외적으로 사전 요청은 credential 정보를 포함할 수 없다. 하지만 응답 헤더에는 Access-Control-Allow-Credentials : true 를 넣어줘야 한다.

레퍼런스

https://developer.mozilla.org/ko/docs/Web/HTTP/CORS
https://developer.mozilla.org/ko/docs/Glossary/CORS
https://jeonghwan-kim.github.io/2023/12/12/cors
https://evan-moon.github.io/2020/05/21/about-cors/#sopsame-origin-policy
https://velog.io/@garcon/%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC-CORS%EC%99%80-credentials
https://junglast.com/blog/http-ajax-withcredential
https://codingmoon.io/posts/interview-questions/describe-cors/
https://codingmoon.io/posts/interview-questions/describe-same-origin-policy/
https://velog.io/@cszzi1006/%EC%B0%A9%ED%95%98%EA%B3%A0-%EC%A2%8B%EC%9D%80-%EC%B9%9C%EA%B5%AC-CORS?utm_source=oneoneone

profile
최선을 다한다는 것은 할 수 있는 한 가장 핵심을 향한다는 것

0개의 댓글