ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

排查实录:server 级配好的安全响应头,为什么部分路由就是不返回?

排查实录:server 级配好的安全响应头,为什么部分路由就是不返回? 现象给一台宝塔 Nginx 的站点加安全响应头写法很常规在 server 块里配置 HSTS、X-Content-Type-Options、X-Frame-Options、Referrer-Policy。nginx -t 通过、reload 成功。然后 curl -I https://example.com/ 首页四个头全在但部分页面一个都没有。实测复现curl -I https://example.com/ 四个头齐全curl -I https://example.com/news/ 一个都没有curl -I https://example.com/assets/app.js 一个都没有同一个 server 块头却看路径下菜。这不是玄学是 add_header 的继承规则。根因add_header 是整体覆盖不是合并Nginx 文档里这句话值得每个运维背下来add_header directives are inherited from the previous configuration level if and only if there are no add_header directives defined on the current level.翻译只要当前层级server、location、if里出现了任意一条 add_header上级的所有 add_header 就全部失效一条都不会继承下来。是整体覆盖不是追加合并。所以server 块里配一次全站生效这个直觉是错的——只要站内存在任何带 add_header 的 location命中它的请求就只会拿到它自己那组头。这个站到底踩了哪些坑坑一include 进来的伪静态文件里有 location。排查时只盯主配置是找不到的。用 nginx -T大写 T输出全量合并后的配置在结果里搜 add_header才能看清每个 location 实际带了什么。坑二if 块里的 add_header。rewrite 模块的 if 和 location 一样内部一旦出现 add_header同样会切断继承。server 级的头会莫名消失多半就是它。坑三正则 location 抢路由。location ~ .(js|css)$ 这类正则的优先级高于普通前缀 location /静态资源请求根本不会进 location /自然拿不到那里配置的安全头。想让某个前缀压过正则得用 ^~ 前缀。修复方案原则安全头四件套写进最外层的 location /凡是自带 add_header 的 location比如给静态资源配 immutable 缓存的把四件套原样再写一份。location / { try_files $uri $uri/ 404; add_header Strict-Transport-Security max-age31536000 always; add_header X-Content-Type-Options nosniff always; add_header X-Frame-Options SAMEORIGIN always; add_header Referrer-Policy strict-origin-when-cross-origin always; } location ^~ /assets/ { expires 365d; add_header Cache-Control public, max-age31536000, immutable always; add_header Strict-Transport-Security max-age31536000 always; add_header X-Content-Type-Options nosniff always; add_header X-Frame-Options SAMEORIGIN always; add_header Referrer-Policy strict-origin-when-cross-origin always; } 两个细节一是每条 add_header 都带 always否则 4xx/5xx 响应不会带这些头二是模板默认注释掉的 error_page 404 /404.html 记得放开软 404 和缓存策略叠加会把 SEO 一起拖下水。 # 怎么验证 1. nginx -T | grep -n add_header看清每个 location 实际拥有的头不要只看主配置文件。 2. 按路径类型逐个 curl -I/、/news/、/assets/xx.js、/xxx不存在的路径一类都不能漏。 3. 验 HTTP/2 别用 curl -w %{http_version}——本机走代理时它显示的是到代理那一段的版本会永远报 1.1 造成误判。用 echo | openssl s_client -connect 域名:443 -servername 域名 -alpn h2,http/1.1输出 ALPN protocol: h2 才算真开了。 # 小结 add_header 的继承规则是有则不继当前层有一条上级全作废。排查顺序固定三步nginx -T 看全量 → 找出所有带 add_header 的层级 → 每层补齐安全头。改完按路径类型逐个 curl 验证别信配了就该全站生效的直觉。
返回列表