应使用 location 块按文件后缀(如.(js|css|json|xml|svg|woff2?)$)精准添加 X-Content-Type-Options: nosniff;进阶可结合 map 提取 $sent_http_content_type 并用 if 判断动态添加,但需确保在 proxy_pass location 中且避免头覆盖。

不能直接用 map 指令控制 X-Content-Type-Options 的开关或值——因为 map 只能生成变量,而 add_header 不支持基于变量条件性添加(它要么全加、要么不加,且不参与请求处理阶段的条件分支)。但你可以通过组合 map + if + add_header(在允许的上下文中)或更稳妥地用 location 匹配实现“按请求特征差异化加固”,核心目标是:对特定静态资源路径或类型,确保 X-Content-Type-Options: nosniff 被准确、稳定地注入。
明确适用场景:按文件后缀精准控制
这是最常用、最可靠的方式。Nginx 原生支持正则匹配静态资源路径,无需引入变量逻辑:
- 直接在
location块中限定常见静态资源扩展名,如\.(js|css|json|xml|svg|woff2?)$ - 在该块内使用
add_header X-Content-Type-Options "nosniff";,确保只对匹配资源生效 - 避免写在
server或http级别全局添加——那样会对 HTML、API 响应等也强制加头,可能干扰正常渲染或框架行为
进阶需求:按上游响应 Content-Type 动态加头
若后端(如 Node.js/Go)返回的 Content-Type 不统一(例如同一路径有时返回 text/plain,有时返回 application/json),而你只想对明确属于静态资源类型的响应加安全头,可用 map 提取并判断:
- 定义 map 映射:
map $sent_http_content_type $should_add_nosniff { default ""; "~*^(text/css|application/javascript|application/json|image/svg+xml)" "1"; } - 在
location块中配合if ($should_add_nosniff = "1") { add_header X-Content-Type-Options "nosniff"; } - ⚠️ 注意:
if在location中仅限简单比较,且必须确保该location是代理到后端的(如proxy_pass),才能读取$sent_http_content_type
规避常见陷阱
很多配置看似生效,实则被覆盖或未触发:
-
不要在
if外层套add_header:Nginx 中add_header继承规则特殊,父级设置会被子级同名头完全覆盖,而非合并 - 避免与 CDN 或后端重复加头:检查响应实际 Header,确认是 Nginx 注入而非其他环节;如有 CDN,需在 CDN 控制台同步配置或关闭其自动加头功能
-
JS/CSS/JSON 必须覆盖:攻击常利用这些类型做 MIME 嗅探,仅给 HTML 加
nosniff不够——浏览器对脚本和样式表的嗅探风险更高
验证是否真正生效
配置完成后,务必实测关键资源:
- 用
curl -I https://yoursite.com/style.css查看响应头中是否有X-Content-Type-Options: nosniff - 访问一个故意设为
Content-Type: text/plain但内容含<script></script>的测试文件,确认浏览器不执行脚本(而是纯文本显示) - 使用 Chrome DevTools → Network → Headers 面板,逐个检查 JS、CSS、JSON 文件的响应头










