防止点击劫持需在nginx中同时配置x-frame-options与content-security-policy的frame-ancestors指令:前者提供广泛兼容的兜底防护(deny/sameorigin),后者支持多源精细控制(如'self' https://a.com),二者共存确保现代与旧版浏览器均有效防御。

防止点击劫持,关键是在 Nginx 层设置两个互补的响应头:X-Frame-Options 和 Content-Security-Policy 的 frame-ancestors 指令。单靠一个不够稳妥,双头并用才能兼顾兼容性与精确控制。
用 X-Frame-Options 控制基础嵌入权限
这是浏览器支持最广的防御头,适合兜底。它只认三个值,推荐按场景选择:
- DENY:全站禁止任何 iframe 嵌套,适合登录页、后台、支付确认页等敏感路径
- SAMEORIGIN:默认策略,允许同域名下其他页面(如 app.example.com 嵌套 api.example.com)嵌套,多数业务页面适用
- ALLOW-FROM uri:已不被 Chrome/Firefox 支持,仅 Safari 有限兼容;如需对接旧系统或内网合作方,优先改用 CSP 替代
Nginx 配置示例(放在 server 或 location 块中):
add_header X-Frame-Options "SAMEORIGIN" always;
用 CSP frame-ancestors 实现精细控制
X-Frame-Options 功能单一,而 CSP 的 frame-ancestors 是它的现代演进,支持多源、关键字和更明确的语义:
- 'none' 等效于 DENY
- 'self' 等效于 SAMEORIGIN
- 'self' https://partner.com https://stats.example.org 可同时允许多个可信来源
注意:CSP 必须用英文单引号包裹关键字(如 'self'),且多个来源用空格分隔,不能用逗号。
Nginx 配置示例:
add_header Content-Security-Policy "frame-ancestors 'self' https://dashboard.example.com;" always;
按路径差异化配置,避免功能受损
一刀切容易误伤正常需求。比如百度统计的点击图、客服 SDK、或官网首页嵌入宣传页,都依赖 iframe 加载:
- 对 /login、/admin、/api/transfer 这类路径,单独设为 DENY 或 'none'
- 对 /about、/public/demo 等开放页面,可设 SAMEORIGIN 或留白(不设头,由浏览器默认策略决定)
- 若第三方工具(如统计平台)要求嵌入,显式写入 CSP frame-ancestors,不要退回 ALLOW-FROM
示例 location 配置:
location /login {
add_header X-Frame-Options "DENY" always;
add_header Content-Security-Policy "frame-ancestors 'none';" always;
}
验证是否真正生效,别只看配置文件
加了头 ≠ 起作用。常见失效原因包括:后端代码覆盖响应头、HTTPS 未启用导致 HTTP 请求无头、add_header 写在 if 块里未触发、或被上游代理清除。
- 打开浏览器开发者工具 → Network → 刷新任意页面 → 查看响应头,确认两个头都存在且值正确
- 用 curl 快速检查:curl -I https://yoursite.com/login
- 建一个本地 HTML 文件,用 iframe 尝试加载你的目标页,观察是否被浏览器拦截并报错











