网站如何防止被iframe引用

X-Frame-Options

X-Frame-Options 通常存在三个值,被设置在服务端返回头(Response Header)中:

1
2
3
X-Frame-Options: DENY
X-Frame-Options: SAMEORIGIN
X-Frame-Options: ALLOW-FROM uri #此用法被弃用,可能不被支持

如果设置为 DENY,不光在别人的网站 frame 嵌入时会无法加载,在同域名页面中同样会无法加载。另一方面,如果设置为 SAMEORIGIN,那么页面就可以在同域名页面的 frame 中嵌套。

DENY

表示该页面不允许在 frame 中展示,即便是在相同域名的页面中嵌套也不允许。

SAMEORIGIN

表示该页面可以在相同域名页面的 frame 中展示。规范让浏览器厂商决定此选项是否应用于顶层、父级或整个链,有人认为该选项不是很有用,除非所有的祖先页面都属于同一来源(origin)。参见浏览器兼容性以获取详细的兼容性信息。

ALLOW-FROM uri 已弃用

这是一个被弃用的指令,不再适用于现代浏览器,请不要使用它。在支持旧版浏览器时,页面可以在指定来源的 frame 中展示。请注意,在旧版 Firefox 上,它会遇到与 SAMEORIGIN 相同的问题——它不会检查 frame 所有的祖先页面来确定他们是否是同一来源。Content-Security-Policy HTTP 首部有一个 frame-ancestors 指令,你可以使用这一指令来代替。

备注: 使用 <meta> 标签来设置 X-Frame-Options 是无效的!例如 <meta http-equiv="X-Frame-Options" content="deny"> 没有任何效果。不要这样用!只有当像下面示例那样设置 HTTP 头 X-Frame-Options 才会生效。

CSP: frame-ancestors

HTTP 头部 Content-Security-Policy (CSP) 指令指定了一个可以包含<frame><iframe><object><embed>,or <applet>等元素的有效父级。

frame-ancestors 被设置成 none 时,类似于 X-Frame-Options: DENY

该指令不支持通过 <meta> 元素或通过 Content-Security-policy-Report-Only 头域所指定。

frame-ancestors 策略可以设置一个或多个源 <source>

1
2
Content-Security-Policy: frame-ancestors <source>;
Content-Security-Policy: frame-ancestors <source> <source>;
可以是如下内容:

<host-source>

一个 Internet 主机的名称或 IP 地址,以及一个可选的URL scheme和/或端口号。这些站点的地址可以包含一个可选的引导通配符(星号, ‘*‘),或者你可以使用通配符(同样还是, ‘*‘)作为端口地址,以示这个源的所有合法端口地址都是有效的。
例子:

  • http://*.example.com: 匹配所有使用 http:URL scheme 并来对于 example.com 及其子域名的加载意图。
  • mail.example.com:443: 匹配所有对于 mail.example.com 在 443 端口的访问意图。
  • https://store.example.com: 匹配所有使用 https:访问 store.example.com 的意图。

<scheme-source>

一个 schema 配置,比如’http:’或’https:’。注意,冒号是必要的。你同样也可以指定一个 data schema(但并不推荐)。

  • 'data:' 允许 data: URIs 作为内容源。 这是不安全的,攻击者可以用此来注入恶意代码。请谨慎使用,并不要令其作用于脚本。
  • 'mediastream:' 允许 mediastream: URIs 作为内容源。
  • 'blob:' 允许 blob: URIs 作为内容源。
  • 'filesystem:' 允许 filesystem: URIs 作为内容源。

'self'

指向一个该受保护文档所在的源,包含同样的 URL schema 和端口号。必须用单引号设置。有些浏览器会从源指令中排除 blob和filesystem。需要允许这些内容类型的站点可以通过 Data 属性指定它们。

'none'

指向一个空集,意味着没有 URL 会被匹配。也需要单引号包裹设置。

一般来说,建议将 X-Frame-Options: <value>Content-Security-Policy: frame-ancestors <source> 联合使用。因为 X-Frame-Options 是一种非标准的写法(当然,浏览器也支持这种写法)。但是相对CSP标准而言,在IE浏览器下不支持 frame-ancestors,仅支持 X-Frame-Options。相对于Chrome与FireFox来讲,若两者均存在,会优先读取 frame-ancestors的值。所以将二者同时使用是一个更好的操作。

JS代码判断

当然,JS代码也可以判断当前页面是否被另一页面进行iframe嵌套。但是通常情况下,并不赞成通过JS代码来进行判断。

代码如下:

1
2
3
if(window.top !== window.self){
// todo next
}

参考


网站如何防止被iframe引用
https://toflying.com/2022/07/06/5-website-block-iframe/
作者
KingChen
发布于
2022年7月6日
许可协议