Ngoài DEBUG = False và ALLOWED_HOSTS (xem [[#9244]]), Django có nhóm setting SECURE_* cần bật cho production.
Cách nhanh nhất để biết còn thiếu gì: chạy python manage.py check --deploy — Django liệt kê hết.
python
# settings/prod.py
SECRET_KEY = os.environ['DJANGO_SECRET_KEY']
# HTTPS
SECURE_SSL_REDIRECT = True # http://... → https://...
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') # khi sau load balancer
SECURE_HSTS_SECONDS = 31536000 # 1 năm
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
# Cookie an toàn
SESSION_COOKIE_SECURE = True # chỉ gửi qua HTTPS
SESSION_COOKIE_HTTPONLY = True # JS không đọc được
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SAMESITE = 'Lax' # 'Strict' nếu không cross-site
# Header bảo vệ
SECURE_CONTENT_TYPE_NOSNIFF = True # chống MIME-sniffing
SECURE_REFERRER_POLICY = 'strict-origin-when-cross-origin'
X_FRAME_OPTIONS = 'DENY' # chống clickjacking- Hai thứ phải cẩn thận.
- HSTS preload là cam kết dài hạn — đặt sai sẽ kẹt site ở HTTPS với mọi subdomain trong nhiều tháng.
- Test với
SECURE_HSTS_SECONDS = 60trước rồi mới tăng dần lên 1 năm.SECURE_PROXY_SSL_HEADERchỉ set khi thực sự có proxy strip TLS (Cloudflare, nginx, Vercel) — đặt nhầm là cho phép attacker spoof HTTPS qua headerX-Forwarded-Proto: https.
Beyond DEBUG = False + ALLOWED_HOSTS (see [[#9244]]), Django has a SECURE_* group that must be on for production.
Run python manage.py check --deploy and Django lists what is missing.
python
# settings/prod.py
SECRET_KEY = os.environ['DJANGO_SECRET_KEY']
# HTTPS
SECURE_SSL_REDIRECT = True # http://... → https://...
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') # behind a load balancer
SECURE_HSTS_SECONDS = 31536000 # 1 year
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
# Safe cookies
SESSION_COOKIE_SECURE = True # HTTPS-only
SESSION_COOKIE_HTTPONLY = True # JS cannot read
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SAMESITE = 'Lax' # 'Strict' if no cross-site
# Protective headers
SECURE_CONTENT_TYPE_NOSNIFF = True # blocks MIME-sniffing
SECURE_REFERRER_POLICY = 'strict-origin-when-cross-origin'
X_FRAME_OPTIONS = 'DENY' # blocks clickjackingPitfall: HSTS preload is a long-term commitment — set it wrong and the site is stuck on HTTPS across every subdomain for months.
- Test with
SECURE_HSTS_SECONDS = 60first then ramp up to a year. - And only set
SECURE_PROXY_SSL_HEADERwhen you actually have a proxy stripping TLS (Cloudflare, nginx, Vercel) — set it wrong and an attacker can spoof HTTPS via anX-Forwarded-Proto: httpsheader.