最基础有效的防护是Nginx配置X-Frame-Options响应头,需加always参数、置于server块顶层、严格拼写,并确认未被CDN/WAF或CSP frame-ancestors覆盖。

直接在 Nginx 中配置 X-Frame-Options 响应头,是最基础、最有效的防止网页被恶意 iframe 嵌套的手段。它不依赖前端代码,也不需要改业务逻辑,只要响应头正确发出,浏览器就会强制执行限制。
怎么配才真正生效
常见失效不是因为不会写,而是配置没覆盖全或被中间层吃掉:
- 必须加 always 参数,否则 404、500、302 等非 200 响应不会携带该头——攻击者常利用错误页绕过防护
- 推荐写在
server块顶层,而不是只放在某个location里,避免漏掉静态资源或 API 路径 - 确认没有其他组件覆盖:CDN(如 Cloudflare)、WAF、反向代理默认可能清除自定义头,需单独开启透传或白名单
- 后端框架(如 Express、Django)如果也设置了同名头,会以第一个发出的为准,可能覆盖 Nginx 的配置
三种取值的实际效果和选择建议
拼写必须严格为 X-Frame-Options(大小写敏感、连字符不能少),值只能是以下三者之一:
- DENY:任何网站都不允许嵌套,包括自己。适合登录页、密码重置页、管理后台等绝不该出现在 iframe 中的页面
-
SAMEORIGIN:只允许同协议 + 同域名 + 同端口的页面嵌套。例如
https://a.com可嵌https://a.com/product.html,但不能嵌http://a.com或https://b.com -
ALLOW-FROM uri:已被 Chrome、Firefox、Edge 彻底弃用,不要使用;如需跨域嵌入,应改用 CSP 的
frame-ancestors
为什么加了头还是能被嵌套
加了配置 ≠ 生效。最常踩的坑是头根本没发出来:
- 用浏览器 DevTools → Network → 找目标请求 → Headers → Response Headers,确认是否存在
X-Frame-Options字段 - 检查是否拼错:写成
X-Frame-Option、x-frame-options、X_Frame_Options都无效 - 如果同时设置了
Content-Security-Policy: frame-ancestors,浏览器会直接忽略X-Frame-Options——这是标准行为,不是 bug - 某些 Nginx 模块(如 fastcgi)可能隐藏该头,比如存在
fastcgi_hide_header X-Frame-Options就会导致失效
更现代的替代与共存方案
X-Frame-Options 是兼容性兜底,frame-ancestors 是当前推荐主力:
-
frame-ancestors 'none'等价于DENY,frame-ancestors 'self'等价于SAMEORIGIN - 支持多源:
frame-ancestors 'self' https://admin.example.com https://partner.com(注意单引号、空格分隔、末尾分号) - 语法容错极低:少一个引号、多一个空格、漏掉分号,整条指令就失效
- 生产环境建议两者共存——
X-Frame-Options保老浏览器,frame-ancestors提供灵活性和未来兼容性


















