nginx中应使用add_header ... always;在server或location块中注入hsts、x-content-type-options、x-frame-options等安全头,避免在http块配置、遗漏always参数或误用已弃用的x-xss-protection。

在Nginx作为API网关或反向代理使用时,通过Add_header指令向响应头注入安全防护头,是提升Web应用基础安全性的低成本、高收益手段。但需注意其作用范围、继承规则与常见陷阱。
哪些安全头适合用Add_header注入
以下HTTP响应头可有效缓解常见Web攻击,推荐在Nginx网关层统一添加:
- Strict-Transport-Security(HSTS):强制浏览器仅通过HTTPS访问,防止协议降级和中间人劫持
- X-Content-Type-Options: nosniff:阻止MIME类型嗅探,防范XSS与资源误解析
- X-Frame-Options: DENY 或 SAMEORIGIN:防御点击劫持(Clickjacking)
- X-XSS-Protection: 1; mode=block(仅对旧版IE/Edge有效,现代浏览器已弃用,可选)
- Content-Security-Policy(CSP):最有力的XSS防御机制,但需按业务精细配置,不建议简单全局设置
Add_header的生效范围与覆盖逻辑
Add_header只对当前作用域(server、location、if)内**成功返回的响应**(状态码2xx、3xx)生效,且不会继承父块配置。这意味着:
- 在
http{}块中添加,对所有server无效;必须在server{}或location{}中显式声明 - 多个
Add_header同名指令会完全覆盖前一个,而非合并(例如两次设置X-Frame-Options,只有后者生效) - 若后端应用(如Spring Boot、Django)本身已输出某安全头,Nginx默认不会覆盖**,除非使用
add_header ... always;
正确写法示例与关键细节
以下为典型网关配置片段,兼顾安全性与兼容性:
server {
listen 443 ssl;
server_name api.example.com;
<pre class="brush:php;toolbar:false;"># 启用HSTS(仅对HTTPS生效,max-age至少15768000秒 ≈ 6个月)
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# 阻止MIME嗅探 & 点击劫持
add_header X-Content-Type-Options nosniff always;
add_header X-Frame-Options DENY always;
# 若需允许嵌入特定域名,改用:SAMEORIGIN 或 ALLOW-FROM https://trusted-site.com
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
# 强制覆盖后端可能返回的不安全X-Frame-Options(如ALLOWALL)
add_header X-Frame-Options DENY always;
}}
⚠️ 注意:always参数至关重要——它让头字段在重定向(301/302)、错误响应(4xx/5xx)等场景也生效,否则默认仅作用于2xx/3xx成功响应。
需要避免的典型错误
- 在
http{}块中写Add_header,导致全站失效 - 遗漏
always,使HSTS或CSP在404、502等错误页丢失,形成安全缺口 - 盲目添加
Content-Security-Policy却未适配前端资源路径,导致页面功能异常 - 将
X-XSS-Protection当作主要防护手段,忽略更有效的CSP和输入输出编码










