nginx 中配置安全响应头需在启用 https 的 server 块内、listen 443 ssl 后立即使用 add_header 指令并加 always 参数,确保 hsts、csp 等头对所有状态码生效,且须按实际业务定制,避免误配导致子站不可用或白屏。

在 Nginx 中通过 ngx_http_headers_module 添加安全响应头,核心是使用 add_header 指令,并严格遵循作用域与状态码覆盖规则。这个模块是 Nginx 编译时默认内置的,无需额外安装,但配置位置和参数选择直接影响安全性是否真正生效。
必须放在 server 块内,且紧贴 SSL 配置
安全头要与站点实际 HTTPS 状态绑定,不能写在全局 http 块顶层。否则 HTTP 站点会误带 HSTS,子站可能因 CSP 过严而白屏。正确做法是在每个启用 HTTPS 的 server 块中配置:
-
listen 443 ssl;后立即添加安全头,确保与证书配置逻辑一致 - 避免仅写在
location /内——PHP、API 或静态资源等子路径若另有location块,会覆盖外层设置 - 宝塔用户可在【网站 → 设置 → 配置文件】中直接编辑该
server块
务必带上 always 参数
默认情况下 add_header 只对 2xx、3xx(如 301/302)和部分 4xx 响应生效,但 404、500、301 跳转页同样需要防护。不加 always,HSTS 就不会被浏览器记住,CSP 也无法拦截错误页中的 XSS 载荷:
- ✅ 正确:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; - ❌ 无效:
add_header X-Frame-Options "DENY";(404 页面不携带) - Nginx ≥ 1.7.5 才支持
always;旧版本需手动在每个location块重复添加
按站点实际业务定制关键头
安全头不是复制粘贴就能用,尤其 HSTS 和 CSP 必须匹配真实部署情况:
-
HSTS:启用
includeSubDomains前,确认所有子域(如api.example.com)已稳定支持 HTTPS,否则会导致子站无法访问 -
CSP:不能照搬模板。用了 Google Fonts 就加
font-src fonts.gstatic.com;;嵌了 YouTube 视频就加frame-src youtube.com; - 初期建议先用
Content-Security-Policy-Report-Only收集违规日志,观察 1–2 周再切正式策略
常用安全头推荐写法
以下为生产环境常见组合,全部带 always,适用于绝大多数 HTTPS 站点:
add_header X-Content-Type-Options "nosniff" always;add_header X-Frame-Options "DENY" always;add_header X-XSS-Protection "1; mode=block" always;add_header Referrer-Policy "strict-origin-when-cross-origin" always;add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;











