CORS (Cross-Origin Resource Sharing) là cơ chế browser bắt server xác nhận đồng ý trước khi cho domain khác gọi API.
- Khi SPA ở
app.example.comfetch tớiapi.example.com, browser sẽ gửi preflightOPTIONSrồi check headerAccess-Control-Allow-*trong response — không pass là không cho gọi thật. - Django không có CORS built-in, dùng
django-cors-headers.
bash
pip install django-cors-headerspython
# settings.py
INSTALLED_APPS = [..., 'corsheaders']
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware', # PHẢI đặt TRƯỚC CommonMiddleware
'django.middleware.common.CommonMiddleware',
# ...
]
# Whitelist exact origin — đừng wildcard với credential
CORS_ALLOWED_ORIGINS = [
'https://app.example.com',
'http://localhost:3000',
]
CORS_ALLOW_CREDENTIALS = True # gửi cookie/Auth headerKhông bao giờ set CORS_ALLOW_ALL_ORIGINS = True cùng với CORS_ALLOW_CREDENTIALS = True — browser sẽ tự reject combo này theo spec, và về mặt logic là bạn đang mở cửa cho mọi website đọc dữ liệu user đã login.
- Cũng đừng nhầm CORS với CSRF: CORS quản ai được phép gọi, CSRF quản request đó có hợp lệ với user hiện tại không.
- Cả 2 đều cần thiết với cookie-based auth.
CORS (Cross-Origin Resource Sharing) is the browser mechanism that forces a server to explicitly allow other domains to call the API.
- When an SPA at
app.example.comfetchesapi.example.com, the browser sends anOPTIONSpreflight and checksAccess-Control-Allow-*response headers before allowing the real call. - Django has no built-in CORS → use
django-cors-headers.
bash
pip install django-cors-headerspython
# settings.py
INSTALLED_APPS = [..., 'corsheaders']
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware', # MUST sit BEFORE CommonMiddleware
'django.middleware.common.CommonMiddleware',
# ...
]
# Whitelist exact origins — never wildcard with credentials
CORS_ALLOWED_ORIGINS = [
'https://app.example.com',
'http://localhost:3000',
]
CORS_ALLOW_CREDENTIALS = True # send cookies/Auth headers
# Optional: tighten methods/headers
CORS_ALLOWED_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS']
CORS_ALLOW_HEADERS = ['authorization', 'content-type', 'x-csrftoken']Pitfall: Never combine CORS_ALLOW_ALL_ORIGINS = True with CORS_ALLOW_CREDENTIALS = True — browsers reject the combo (per spec), and logically it opens the door for any site to read a logged-in user's data.
- Do not confuse CORS with CSRF: CORS controls who is allowed to call, CSRF controls whether the request is legitimate for the current user.
- Both are needed with cookie-based auth.