最稳妥做法是在每个https的server块中配置add_header并加always参数,安全头须与listen 443 ssl同作用域,紧随ssl证书配置之后、location之前,且需按站点实际定制hsts和csp策略。

直接在每个 HTTPS 的 server 块里配置 add_header 指令,并加上 always 参数,是最稳妥、最推荐的做法。安全头必须和 listen 443 ssl 共存于同一作用域,不能写在全局 http 块或 HTTP(80端口)的 server 块中。
必须紧贴 SSL 配置放置
安全头要放在启用 HTTPS 的 server 块内,且建议紧随 ssl_certificate 和 ssl_certificate_key 之后、任意 location 块之前。这样能确保策略与证书状态、子域范围、资源加载逻辑精准匹配。
例如:
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
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 Content-Security-Policy "default-src 'self'; script-src 'self'; connect-src 'self';" always;
}
务必带上 always 参数
默认情况下,add_header 只对 2xx 成功响应生效。但 301/302 重定向、404 页面、500 错误页同样需要防护——否则 HSTS 不会被浏览器记住,CSP 在错误页失效,攻击者可能利用这些缺口绕过策略。
所以每条 add_header 后都应加 always,避免策略断层。
按站点实际定制关键策略
-
HSTS 的
includeSubDomains要谨慎启用:一旦开启,所有一级子域(如api.example.com、cdn.example.com)必须已部署有效 HTTPS,否则会锁死访问。 -
CSP 不能照搬模板:
- 用了 Google Fonts?补
font-src fonts.gstatic.com; - 嵌了 YouTube 视频?加
frame-src youtube.com; - 初次上线建议先用
Content-Security-Policy-Report-Only模式收集两周报告,再切正式拦截。
- 用了 Google Fonts?补
避免常见冲突与误配
- 不要同时配置
X-Frame-Options和Content-Security-Policy的frame-ancestors:浏览器优先采用 CSP,前者会被忽略;新项目直接用frame-ancestors 'self'更灵活,旧系统可保留X-Frame-Options作兼容。 - 全局配置(
http{}块)易误伤:HTTP 站点不该带 HSTS,子站也不该继承主站过严的 CSP,导致白屏或功能异常。
不复杂但容易忽略











