Django 的安全响应头有多少是默认就发的?哪些要自己打开?这篇用 Client 直接看响应头,再用 manage.py check --deploy 给一个最小项目「体检」,最后试一下 Django 6 新增的 CSP 中间件。
X-Content-Type-Options nosniff Referrer-Policy same-origin Cross-Origin-Opener-Policy same-origin X-Frame-Options DENY Strict-Transport-Security (没有) Content-Security-Policy (没有) Content-Security-Policy-Report-Only (没有)
注意 X-Frame-Options 来自 XFrameOptionsMiddleware,不是 SecurityMiddleware;两个都要在 MIDDLEWARE 里。
https 请求 status 200 Strict-Transport-Security: max-age=31536000; includeSubDomains; preload http 请求 status 200 Strict-Transport-Security: (没有)
HSTS 告诉浏览器「以后只用 HTTPS 访问这个域名」,只在 HTTPS 响应上发才有意义。浏览器收到后的行为发生在浏览器里,本文没有验证。开 preload 之前要确认所有子域名都能走 HTTPS,这是设计上的提醒,本文没有做实验。
http GET / → 301 Location: https://localhost/ http GET /healthz/ → 404 Location: (无)
默认: 4 条警告 ['security.W003', 'security.W004', 'security.W008', 'security.W009']
加固后: 1 条警告 ['security.W003']
默认时各警告的含义(每条第一行):
security.W003 You don't appear to be using Django's built-in cross-site request forgery protection via the mi
security.W004 You have not set a value for the SECURE_HSTS_SECONDS setting. If your entire site is served onl
security.W008 Your SECURE_SSL_REDIRECT setting is not set to True. Unless your site should be available over
security.W009 Your SECRET_KEY has less than 50 characters, less than 5 unique characters, or it's prefixed wi这个命令只检查设置,不检查你的服务器配置。加固后剩下的 W003 是因为我的最小中间件列表里没有 CsrfViewMiddleware,真实项目里不会出现。
X-Content-Type-Options nosniff Referrer-Policy same-origin Cross-Origin-Opener-Policy same-origin X-Frame-Options DENY Strict-Transport-Security (没有) Content-Security-Policy default-src 'self'; frame-ancestors 'none' Content-Security-Policy-Report-Only default-src 'self'; img-src https:
Django 6 之前要靠第三方包(django-csp 等)。CSP 策略写错会拦掉页面自己的脚本和样式,所以先用 SECURE_CSP_REPORT_ONLY 观察,本文只验证了响应头的生成,没有验证浏览器的拦截与上报。