iframe特性全解读
前言
在平时的开发中,或多或少会用到iframe,大部分时候我们只需要简单的使用iframe标签,设置个宽高即可,很少回去深究iframe的别的特性。比如这种用法:
<iframe src='https://blog.5udou.cn'>
但直到产品经理要求说,iframe嵌入的页面可不可以让主页面的url地址发生变化呀?好吧,一下子懵圈了,我得去查查资料,于是索性就深究深究iframe的一些特性,免得再次尴尬。
下面所有代码都可以在这里找到:https://github.com/linxiaowu66/iframe-demo
iframe的特性
iframe的特性都是依赖参数配置实现的,现整理如下有用的属性:
属性 | 解释 | 备注 |
---|---|---|
allow | 可以为iframe指定特性策略 | |
allowfullscreen | 是否允许iframe调用requestFullscreen()方法激活全屏模式,这个属性等同于allow属性的这个配置:allow="fullscreen" | |
allowpaymentrequest | 是否允许一个跨域的iframe调用支付请求API | |
csp | 内嵌的资源强制实行同源策略 | |
height | iframe的高度,默认150px | |
importance | 标识在iframe属性src指示的资源的下载优先级,有auto /high /low 三个等级 | |
name | 内嵌的浏览内容的目标名称 | |
referrerpolicy | 指示当获取frame的资源的时候携带的referrer,默认是no-referrer-when-downgrade ,也就是仅当发生协议降级(如 HTTPS 页面引入 HTTP 资源,从 HTTPS 页面跳到 HTTP 等)时不发送 Referrer 信息。这个规则是现在大部分浏览器默认所采用的; | |
sandbox | 在frame上的内容上运用额外的一下限制,具体哪些字段我们下面详细解释 |
iframe的allow属性详解
allow属性的使用需要参考特性策略这一小节。特性策略可以允许你控制页面或者iframe可以使用哪些特性。页面控制的话设置在HTTP头部的Feature-Policy的这个字段,iframe的话就是我们要说的这个allow字段。
特性策略的书写规则是:<feature name> <allowlist of origin(s)>
完整的特性名称参考: Policy Controlled Features或者Feature-Policy
而allowlist则有如下规则:
*
:表示该特性在该文档下都是允许的,包括所有的嵌套的浏览内容(iframes),而不用管这些内容的源。self
:表示该特性在该文档下都是允许的,并且仅在同源的情况下嵌套的浏览内容(iframes)才可以使用。src
:(iframes的allow属性专用)表示该特性在这个iframe下允许使用,只要加载的文档来源的源和iframe的src
属性指定的URL是同源的。none
:表示该特性在顶层以及嵌套的浏览内容下都是被禁用的<origin(s)>
:表示该特性只在一些指定的源下才允许使用,多个源使用空格隔开
今天我们主要讲一下iframe下的allow属性,比如你不允许iframe的页面全屏、不允许调用摄像头之类的行为,可以这么配置:
<iframe allow="camera 'none'; fullscreen 'none'">
比如只允许同源的才可以使用全屏这个特性:
<iframe src="https://example.com..." allow="fullscreen 'src'"></iframe>
比如只允许指定源才可以使用定位功能:
<iframe src="https://google-developers.appspot.com/demos/..." allow="geolocation https://google-developers.appspot.com"></iframe>
iframe的referrerpolicy属性详解
这个属性牵扯到了HTTP的referer策略,我们知道referer的策略是这样的:
- No Referrer:任何情况下都不发送 Referrer 信息;
- No Referrer When Downgrade:仅当发生协议降级(如 HTTPS 页面引入 HTTP 资源,从 HTTPS 页面跳到 HTTP 等)时不发送 Referrer 信息。这个规则是现在大部分浏览器默认所采用的;
- Origin Only:发送只包含 host 部分的 Referrer。启用这个规则,无论是否发生协议降级,无论是本站链接还是站外链接,都会发送 Referrer 信息,但是只包含协议 + host 部分(不包含具体的路径及参数等信息);
- Origin When Cross-origin:仅在发生跨域访问时发送只包含 host 的 Referrer,同域下还是完整的。它与 Origin Only 的区别是多判断了是否 Cross-origin。需要注意的是协议、域名和端口都一致,才会被浏览器认为是同域;
- Unsafe URL:无论是否发生协议降级,无论是本站链接还是站外链接,统统都发送 Referrer 信息。正如其名,这是最宽松而最不安全的策略;
比如我们这样配置:
<iframe allow="fullscreen 'none'" referrerpolicy="no-referrer" src='http://127.0.0.1:3000/iframe.html'></iframe>
我们通过抓包可以看到对应的请求是这样的:
iframe的sandbox属性详解
iframe的沙箱模式可以提供一些额外的配置,当你把一个iframe置为沙箱的时候,意味着沙箱内的内容的行为全凭你控制了。
比如你在iframe下这样配置:
<iframe sandbox="" src='http://127.0.0.1:3000/iframe1.html'></iframe>
但是iframe1.html中却有对应的js脚本,那么在控制台下可以看到这样的报错:
Blocked script execution in 'http://127.0.0.1:3000/iframe1.html' because the document's frame is sandboxed and the 'allow-scripts' permission is not set.
所以当你的iframe有脚本的时候,基本上都会配置allow-scripts
这个属性。
再比如你的页面会有form标签提交数据的时候,如果没有allow-forms
,则会报这种错误:
Blocked form submission to '' because the form's frame is sandboxed and the 'allow-forms' permission is not set.
接下来解释一下各个配置的含义:
属性 | 解释 |
---|---|
allow-forms | 允许资源提交表单 |
allow-modals | 允许资源打开模态窗口,比如window.alert()、window.confirm()、window.print()、window.prompt() |
allow-orientation-lock | 允许资源锁住屏幕方向 |
allow-pointer-lock | 允许资源使用Pointer Lock API |
allow-popups | 允许弹出窗口(比如window.open(), target="_blank", 或者showModalDialog()),如果这个关键词没有的话,弹出窗口将会静默地打开失败 |
allow-popups-to-escape-sandbox | 允许沙箱文档打开新窗口,而这些新窗口不需要继承沙箱模式。 |
allow-presentation | 允许嵌入者控制是否iframe启用一个展示会话 |
allow-same-origin | 允许将内容作为普通来源对待。如果未使用该关键字,嵌入的内容将被视为一个独立的源。 |
allow-scripts | 允许嵌入的浏览上下文运行脚本(但不能创建弹窗) |
allow-top-navigation | 允许嵌入的页面的上下文可以导航(加载)内容到顶级的浏览上下文环境(browsing context)。如果未使用该关键字,这个操作将不可用 |
allow-storage-access-by-user-activation | 允许嵌入的页面请求通过Storage Access API使用父页面的存储能力 |
allow-top-navigation-by-user-activation | 允许嵌入的页面的上下文可以导航(加载)内容到顶级的浏览上下文环境(browsing context),但是只能通过用户手势主动调用来初始化 |
关于沙箱模式的注意点
- 当被嵌入的文档与主页面同源时,强烈建议不要同时使用
allow-scripts
和allow-same-origin
,否则的话将允许嵌入的文档通过代码删除sandbox
属性。虽然你可以这么做,但是这样的话其安全性还不如不用sandbox。 - 如果攻击者可以将潜在的恶意内容往用户的已沙箱化的iframe中显示,那么沙箱操作的安全性将不再可靠。推荐把这种内容放置到独立的专用域中,减小可能的损失。
- 沙箱属性(sandbox)在Internet Explorer 9及更早的版本上不被支持
经过上面的解释,想必知道刚开始的那个问题的答案了吧?
Tips
- window.frames
frames属性是一个类似数组的对象;因为frames实际上是window对象的别名,frames属性又是可以遍历的,所以它是一个类似数组的对象: window.frames.length === window.length;
frames属性的每一项是框架内的窗口,即框架内的window对象;frames属性的每一项并不是iframe的dom节点!!!若需要获取iframe的dom节点可以通过以下方法:
frames[0].frameElement
如果有一个iframe是处于沙箱模式,并且没有设置allow-same-origin
,那么虽然你可以访问到window.frames的长度为2,但是当你获取window.frames[1].location的时候会有这样的错误:
DOMException: Blocked a frame with origin "http://127.0.0.1:3000" from accessing a cross-origin frame
配置了allow-same-origin
的时候:
没有配置allow-same-origin
的时候:
-
window.top: 顶层窗口,即最上层的窗口
-
window.parent: 父窗口,如果一个窗口没有父窗口,则它的parent属性为自身的引用;
-
window.self: 当前窗口,即自身的引用;
参考
公众号关注一波~
网站源码:linxiaowu66 · 豆米的博客
Follow:linxiaowu66 · Github
关于评论和留言
如果对本文 iframe特性全解读 的内容有疑问,请在下面的评论系统中留言,谢谢。