T.I.L May 19, 2023 (Django CORS policy 문제)

2023. 5. 19. 16:00T.I.L (Today_I_Learned)

문제점


Django 프로젝트 진행 중 프론트와 연결을 시도하다가 CORS policy 에러가 발생했습니다.

Access to fetch at 'http://~~~~~~~~~~~~~~~~/~~~~~/~~~~~/' from origin 'http://~~~~~~~~~~~' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.

메시지는 위와 같았습니다.

 

 

시도한 것


1. CORS policy (CORS 정책)이 무엇인지 검색

2. 해결 CORS policy 문제 해결 방법 검색

 

 

알게된 것


1. CORS policy (CORS 정책)

CORS (Cross-Origin Resource Sharing) 정책은 웹 애플리케이션의 보안을 강화하기 위해 사용됩니다. 기본적으로 브라우저는 동일 출처 정책(Same-Origin Policy)에 따라 다른 출처로부터의 리소스 요청을 제한합니다.

 

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

동일 출처 정책은 웹 페이지가 한 출처의 리소스에만 접근할 수 있도록 하여 악의적인 스크립트로부터 사용자 데이터를 보호하는 역할을 합니다.

 

3. SOP(동일 출처 정책) 과 CORS 상관관계

'CORS 에러'라고 알고 있던 것은 사실 브라우저의 SOP 정책에 따라 다른 출처의 리소스를 차단하면서 발생된 에러이며, 'CORS는 다른 출처의 리소스를 얻기 위한 해결 방안' 이었던 것입니다.

요약
SOP 정책을 위반해도 CORS 정책에 따르면 다른 출처의 리소스라도 허용한다는 뜻입니다.

 

4. 브라우저의 CORS 기본 동작

1. 클라이언트에서 HTTP요청 헤더에 Origin을 담아 전달합니다.
	1) 기본적으로 웹은 HTTP 프로토콜을 이용하여 서버에 요청을 보내게 됩니다.
	2) 이때 브라우저는 요청 헤더에 Origin 이라는 필드에 출처를 함께 담아 보내게 됩니다.


2. 서버는 응답헤더에 Access-Control-Allow-Origin을 담아 클라이언트로 전달합니다.
	1) 이후 서버가 이 요청에 대한 응답을 할 때 응답 헤더에 Access-Control-Allow-Origin이라는 필드를 추가하고 값으로 '이 리소스를 접근하는 것이 허용된 출처 url'을 내려보냅니다.


3. 클라이언트에서 Origin과 서버가 보내준 Access-Control-Allow-Origin을 비교합니다.
	1) 이후 응답을 받은 브라우저는 자신이 보냈던 요청의 Origin과 서버가 보내준 응답의 Access-Control-Allow-Origin을 비교해본 후 차단할지 말지를 결정합니다.
	2) 만약 유효하지 않다면 그 응답을 사용하지 않고 버립니다. (CORS 에러 !!)

 

5. CORS policy 문제 해결 방법

부라우저의 CORS 동작 과정을 살펴보니, 백엔드 개발자가 해결해야 할 부분은 서버에서 응답헤더 'Access-Control-Allow-Origin' 필드에 허용할 출처를 기재해서 클라이언트에 응답하는 것이었습니다.

 

 

해결


1. Django에서 제공하는 django-cors-headers 패키지를 설치합니다. 

    => django-cors-headers 패키지는 Django 애플리케이션에 CORS 지원을 쉽게 추가할 수 있도록 도와줍니다.

python -m pip install django-cors-headers

 

2. settings.py 파일에서 INSTALLED_APPS 항목에 'corsheaders'를 추가합니다.

INSTALLED_APPS = [
    ...,
    "corsheaders",
    ...,
]

 

3. settings.py 파일에서 MIDDLEWARE 항목에 'corsheaders.middleware.CorsMiddleware'를 되도록 맨 위에 위치하도록 추가합니다. 

    => 이렇게 하면 Django의 미들웨어 스택에서 CORS 미들웨어가 가장 먼저 실행됩니다.

MIDDLEWARE = [
    ...,
    "corsheaders.middleware.CorsMiddleware",
    "django.middleware.common.CommonMiddleware",
    ...,
]

 

4. settings.py 파일에서 CORS_ALLOW_ALL_ORIGINS 설정을 True로 설정(작성)하여 모든 출처에서의 요청을 허용하거나, CORS_ALLOWED_ORIGINS 설정을 사용하여 특정 출처만 허용할 수 있습니다.

CORS_ALLOW_ALL_ORIGINS = True

'''
해당 설정은 True로 설정할 경우 모든 출처가 허용됩니다. 허용된 출처를 제한하는 다른 설정은 무시됩니다. 기본값은 False입니다.

해당 설정을 True로 설정하는 것은 위험할 수 있습니다. 왜냐하면 어떤 웹사이트든 본인의 웹사이트로부터의 교차 출처 요청을 할 수 있게 되기 때문입니다. 

일반적으로 CORS_ALLOWED_ORIGINS 또는 CORS_ALLOWED_ORIGIN_REGEXES를 사용하여 허용된 출처 목록을 제한하는 것이 좋습니다.
'''

 

 

출처 & 참고하면 좋은 글


https://inpa.tistory.com/entry/WEB-%F0%9F%93%9A-CORS-%F0%9F%92%AF-%EC%A0%95%EB%A6%AC-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95-%F0%9F%91%8F

 

🌐 악명 높은 CORS 개념 & 해결법 - 정리 끝판왕 👏

악명 높은 CORS 에러 메세지 웹 개발을 하다보면 반드시 마주치는 멍멍 같은 에러가 바로 CORS 이다. 웹 개발의 신입 신고식이라고 할 정도로, CORS는 누구나 한 번 정도는 겪게 된다고 해도 과언이

inpa.tistory.com

 

https://pypi.org/project/django-cors-headers/

 

django-cors-headers

django-cors-headers is a Django application for handling the server headers required for Cross-Origin Resource Sharing (CORS).

pypi.org