CORS

Seongho·2021년 8월 23일
0

프론트엔드

목록 보기
2/2

Cross-Origin Resource Sharing

출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제

웹 애플리케이션은 리소스가 자신의 출처(도메인, 프로토콜, 포트)와 다를 때 교차 출처 HTTP 요청을 실행한다.

https://developer.mozilla.org/ko/docs/Web/HTTP/CORS

무슨 소리인가 싶다. 좀 더 자세히 알아보자.

1. 출처란? (origin?)

웹 컨텐츠에 접근할 때 사용하는 URL의 scheme(프로토콜, 호스트(도메인), 포트)

두 객체의 스킴, 호스트, 포트가 모두 일치하는 경우 같은 출처를 가졌다고 말한다.

동일 출처의 예제

http://example.com/app1/index.html http://example.com/app2/index.html스킴(http)과 호스트(example.com) 일치
http://Example.com:80
http://example.com
HTTP의 기본 포트는 80이므로 동일한 출처

다른 출처의 예제

http://example.com/app1
https://example.com/app2
다른 스킴
http://example.com
http://www.example.com
http://myapp.example.com
다른 호스트
http://example.com
http://example.com:8080
다른 포트

*기본 포트는 80

2. CORS Policy

  • 교차 출처 리소스 공유 정책
  • 말 그대로 서로 다른 출처에서 온 리소스를 공유하는 것에 대한 정책이다.

보안 상의 이유로 브라우저는 교차 출처의 HTTP 요청을 제한한다. 예를 들어, localhost:8080에서 localhost8000으로 XMLHttpRequest등의 요청을 보내는 경우 CORS 정책에 걸려 제한된다. 이런 제한을 해소하고 다른 출처의 리소스를 불러오려면 그 출처에서 올바른 CORS 헤더를 포함한 응답을 반환해야 한다.

예를 들어, https://foo.example의 웹 컨텐츠가 https://bar.other 도메인의 컨텐츠를 호출하기를 원한다고 할 때, 아래와 같이 XMLHttpRequest로 GET 요청을 보낸 경우,

const xhr = new XMLHttpRequest();
const url = 'https://bar.other/resources/public-data/';

xhr.open('GET', url);
xhr.onreadystatechange = someHandler;
xhr.send();

GET 요청의 헤더는 다음과 같다.

GET /resources/public-data/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
Origin: https://foo.example

이에 대해 서버는 Access-Control-Allow-Origin 헤더를 포함한 응답을 보내야 CORS가 해결된다.

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml

[…XML Data…]

위의 경우 모든 도메인에서 해당 리소스(bar.other)에 접근할 수 있음을 의미한다. https://foo.example의 요청만 허용하려는 경우 다음을 전송한다.

Access-Control-Allow-Origin: https://foo.example

Origin 말고도 Methods나 Headers를 통제할 수도 있다.

Access-Control-Allow-Origin: http://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400

정리

CORS Policy는 허락되지 않은 출처에서 리소스를 요청하여 가져가는 것을 원천적으로 차단하는 정책이고, 브라우저에서 이를 확인한다. 요청을 받은 곳은 요청을 한 곳이 내 리소스를 가져가도 되는 곳인지 알려주는 Access-Control-Allow-Origin 이라는 헤더를 응답에 담아서 브라우저에 전달한다.

Django의 경우 다음 링크에서 이러한 응답을 헤더에 포함하는 방법을 제공하고 있다.

django-cors-headers

간략히 사용법을 알아보자면,

  1. python -m pip install django-cors-headers

  2. installed app에 'corsheaders' 추가

  3. MIDDLEWARE에 추가

    MIDDLEWARE = [
        ...,
        'corsheaders.middleware.CorsMiddleware',
        'django.middleware.common.CommonMiddleware',
        ...,
    ]
  • 조건: CorsMiddleware should be placed as high as possible, especially before any middleware that can generate responses such as Django's CommonMiddleware or Whitenoise's WhiteNoiseMiddleware. If it is not before, it will not be able to add the CORS headers to these responses.
  • 대충 위에 놓으라는 뜻. CorsMiddleware는 그냥 맨 위에 놓자.
  1. CORS ALLOWED ORIGINS 추가

    응답 헤더를 직접 설정해주는게 아니라 django에서 처리해주는듯

    CORS_ALLOWED_ORIGINS = [
        "https://example.com",
        "https://sub.example.com",
        "http://localhost:8080",
        "http://127.0.0.1:9000"
    ]

    여기에 해당하는 애들은 허용한다.

클라이언트측에서 뭔가 해야 하는건가? 라고 생각 했었는데 기본적으로 정보 요청을 받은 쪽에서 정보 요청한 곳이 허용된 출처인지를 알려주는 형태였다. 만약 8000 vue.js 포트에서 8080 서버로 요청을 보낸 경우 서버에서 응답에 8000을 허용한다는 헤더를 담아서 리소스를 제공해야 한다.

0개의 댓글