웹 개발을 하다보면 CORS(Cross-Origin Resource Sharing)와 같은 보안 이슈들이 흔히 발생합니다. 이는 브라우저가 서로 다른 호스트(도메인) 간의 자원 공유를 제한함으로써, 웹 애플리케이션의 보안을 강화하는 중요한 기능입니다. 이러한 제한의 근본적인 이유는 보안 취약점을 방지하기 위함인데, 예를 들어, CSRF(Cross-Site Request Forgery)와 같은 공격에서는 악의적인 웹사이트가 사용자의 브라우저에 저장된 인증 정보를 이용하여 다른 사이트에 요청을 보내는 행위를 막기 위함입니다.
데이터 엔지니어로 전향한 후에 오랜만에 서버 개발을 하려고 했더니 개념이 정확히 기억도 안 나고 사실 오랜만에 세션으로 인증을 구현할 일이 있어서 조금 헤맸습니다. CORS, CSRF, 쿠기, 인증등… 오랜만에 보니 머리아파서 넘겼던 부분들을 정리해보려고 합니다.
CORS (Cross-Origin Resource Sharing)
CORS는 다른 출처(origin)의 웹 페이지가 해당 출처의 자원에 접근할 수 있도록 하는 메커니즘입니다. 기본적으로 웹 브라우저는 동일 출처 정책(Same-Origin Policy)을 따르기 때문에 다른 출처의 자원에 접근하는 것이 제한되게 하는데 이를 제한합니다. 하지만, 요즘은 대부분 Front와 Backend Application은 보통 다른 Host를 갖게 되기 때문에 HTTP 통신 시 서버에서 관련 Header의 값을 설정해야 합니다.
서버 측에서 HTTP 응답 헤더에 다음과 같은 내용을 포함시키면 CORS 문제를 해결할 수 있습니다.
Access-Control-Allow-Origin: 통신할 Front Host
모든 Host에서 요청을 허용하려면 아래와 처럼 HTTP 응답 헤어데 다음과 같은 내용을 포함시키면 모든 도메인에서 요청을 허용할 수 있습니다. → 하지만, 보안적으로 좋지 않기 때문에 추천 드리지 않습니다.
Access-Control-Allow-Origin: *
응답 헤더에 Access-Control-Allow-Origin 추가하기
1. 직접 Middleware를 추가해서 해당 Header를 추가하기 (추천하지 않음.)
직접 middleware class를 정의한 후 setting.py에 MIDDLEWARE에 추가해주는 방법 있습니다.
대략적으로 www.doosikbae.com이라는 도메인에서 요청을 허용하려면 아래처럼 응답 HEADER를 변경할 수 있습니다.
class SimpleCorsMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
if request.method == 'OPTIONS' and "HTTP_ACCESS_CONTROL_REQUEST_METHOD" in request.META:
response = self.preflight_response(request)
return response
response["Access-Control-Allow-Origin"] = "https://www.doosikbae.com"
return response
def preflight_response(self, request):
response = HttpResponse()
response["Access-Control-Allow-Origin"] = "https://www.doosikbae.com"
response["Access-Control-Allow-Methods"] = "GET,POST,OPTIONS"
response["Access-Control-Allow-Headers"] = "content-type,accept"
response["Access-Control-Max-Age"] = "1800" # 30 minutes cached
return response
# settings
MIDDLEWARE = [
...
'middleware.SimpleCorsMiddleware',
...
]
2. django-cors-headers 이용하기 (추천)
Python의 가장 큰 장점인 풍부한 라이브러리 생태계를 활용하는 것이 보안 및 생산성 측면에서는 추천하는 방법입니다.
해당 라이브러리를 활용하는 방법은 공식 문서에 정말 잘 설명이 되어 있기 때문에 생략하겠습니다.
한 가지만 이야기해 보면 모든 도메인의 요청을 허용하지 말고 허용할 도메인을 설정하는 것을 추천드립니다.
CORS_ALLOW_ALL_ORIGINS = True # 추천 하지 않음.
CORS_ALLOWED_ORIGINS = [
"https://blog.doosikbae.com", # 추천
]
CORS 간단하게 브라우저 콘솔에서 테스트해 보기
fetch('test할 사이트')
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
CORS 관련 설정 테스트를 google.com에서 콘솔에서 진행. (https://www.google.com을 CORS_ALLOWED_ORIGINS 에 넣었을 때와 안 넣었을 때 CORS Policy에 의해 막히는지 테스트)
다음에는 CSRF Token관련 글 k8s에 Django를 배포하면서 겪었던 어려움등에 대해서 포스팅 해보겠습니다.
관련 글 추천
'Computer Engineering > Django' 카테고리의 다른 글
장고는 DB connection을 어떻게 관리할까? (0) | 2023.12.25 |
---|---|
Django에서 CSRF 공격을 막기 및 CSRF 토큰의 이해와 활용 (0) | 2023.11.08 |
Python/Django NewRelic 셋업 및 환경 분리하기. (0) | 2022.06.29 |
Django DB Transaction 3편 - DB Transaction Test 코드 작성하기. (0) | 2022.02.02 |
Django DB Transaction 2편 - 명시적으로 transaction 활용하기. (feat. savepoint) (2) | 2022.01.17 |