欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

用趣味学习法理解iframe的跨域通信

最编程 2024-01-31 13:36:05
...

一、前言

之前的需求迭代,遇到一个iframe跨域通信的问题,域名B的一个接口请求里的字段用到里域名A下的账户id,原本的代码是直接用sessionStorage.getItem(info)的方式从域名A的缓存中获取用户信息,结果没有拿到。

于是,我脑海里回忆iframe相关的知识点,想到不同域名下的信息是无法直接获取的。没错,这个本应该熟悉的iframe基础知识点,我靠几分钟的回忆才想起来。改完需求之后,我想我是时候重拾一下iframe的相关知识了。

以下关于iframe的介绍主要来自MDN


二、基础信息

<iframe>,它是HTML内联框架元素,表示嵌套的browsing context。它能够将另一个HTML页面嵌入到当前页面中。

每个嵌入的浏览上下文(embedded browsing context)都有自己的会话历史记录(session history)和DOM树。包含嵌入内容的浏览上下文称为父级浏览上下文。*浏览上下文(没有父级)通常是由 Window 对象表示的浏览器窗口。


三、属性


3.1 allow

用户为<iframe>指定特征策略


3.1.1 特征策略

简单介绍一下特征策略,特征策略允许web开发者在浏览器中选择启用、禁用和修改确切特征和 API 的行为.比如内容安全策略,但是它控制的是浏览器的特征非安全行为。allow是iframe特有的特征策略,可以控制iframe使用哪些特征。


特征策略的语法

<allowlist>


*: 本特性默认在最上层和包含的内容中(iframes)允许。

'self': 本特性默认在最上层允许,而包含的内容中(iframes)使用源地址相同设定。也就是说本特性在iframe中不允许跨域访问。

'none': 本特性默认在最上层和包含的内容中(iframes)都禁止。

'src': (只在iframe中允许) 只要在src 中的URL和加载iframe用的URL相同,则本特性在iframe中允许。

其中*或'none'只允许单独使用,而'self'和'src'可以与多个源地址一起使用。


3.1.2 语法

禁止全屏模式

可以设置fullscreen的特征策略为'none'。

<iframe allow="fullscreen 'none'">


支持多个特征策略

禁止全屏模式和禁止调起支付接口,多个用分号隔开。

<iframe allow="fullscreen 'none'; payment 'none'">


3.2 csp

对嵌入的资源配置内容安全策略


3.2.1 内容安全策略( CSP )

内容安全策略   (CSP) 是一个额外的安全层,用于检测并削弱某些特定类型的攻击,包括跨站脚本 (XSS (en-US)) 和数据注入攻击等。无论是数据盗取、网站内容污染还是散发恶意软件,这些攻击都是主要的手段。


设置内容安全策略

比如一个引入的css文件,如果我们设置了如下策略,该策略禁止任何资源的加载,除了来自cdn.example.com的样式表。

head中设置安全策略并引入外部的css文件:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'cdn.example.com'; " />
    <title>iframe-child</title>
    <link rel="stylesheet" href="./style.css" />
  </head>
  <body>
    ...
  </body>
</html>

这个时候如果在浏览器打开页面,打开开发者工具就能看到报错:

Refused to load the stylesheet 'file:///Users/Desktop/weblearn/iframe/style.css' because it violates the following Content Security Policy directive: "style-src 'cdn.example.com'". Note that 'style-src-elem' was not explicitly set, so 'style-src' is used as a fallback.

这表示样式表仅允许加载自cdn.example.com,然而该页面企图从自己的加载。


3.3 height

以CSS像素格式HTML5,或像素格式HTML 4.01,或百分比格式指定frame的高度。默认值为150。


3.4 importance

表示 <iframe> 的 src 属性指定的资源的加载优先级。允许的值有:

auto (default):不指定优先级。浏览器根据自身情况决定资源的加载顺序

high:资源的加载优先级较高

low:资源的加载优先级较低


3.4 name

用于定位嵌入的浏览上下文的名称。该名称可以用作 <a> 标签与 <form> 标签的 target 属性值,也可以用作 <input> 标签和 <button> 标签的 formtarget 属性值,还可以用作 window.open() 方法的 windowName 参数值。

用作 <a> 标签的 target 属性值:

<iframe name="myIframe" src="http://www.w3cschool.cc" width="500" height="200"></iframe>
<a href="https://juejin.cn/" target="myIframe">掘金</a>

点击掘金按钮前展示:

网络异常,图片无法展示
|


点击掘金按钮后展示:

image.jpeg


在iframe窗口中打开页面

使用window.open()打开窗口,该方法的第二个参数可以指定窗口名称,我们通过window.name可以拿到iframe的name,赋值到window.open()中。

父页面:

<iframe name="myIframe" src="./child.html" width="500" height="200"></iframe>

iframe页面:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>iframe-child</title>
  </head>
  <body>
    <div>
      <input type="button" id="open" value="打开弹窗" />
    </div>
    <script>
      window.onload = function () {
        var div = document.querySelector('div');
        document.querySelector('#open').onclick = function () {
          window.open('https://juejin.cn/', window.name);
        };
      };
    </script>
  </body>
</html>

可以在当前iframe窗口中打开掘金的页面:

image.jpeg


3.5 referrerpolicy

表示在获取 iframe 资源时如何发送 referrer 首部:

no-referrer: 不发送 Referer 首部。

no-referrer-when-downgrade (default): 向不受 TLS (HTTPS) 保护的 origin 发送请求时,不发送 Referer 首部。

origin: referrer 首部中仅包含来源页面的源。换言之,仅包含来源页面的 scheme, host, 以及 port (en-US)。

origin-when-cross-origin: 发起跨域请求时,仅在 referrer 中包含来源页面的源。发起同源请求时,仍然会在 referrer 中包含来源页面在服务器上的路径信息。

same-origin: 对于 same origin (同源)请求,发送 referrer 首部,否则不发送。

strict-origin: 仅当被请求页面和来源页面具有相同的协议安全等级时才发送 referrer 首部(比如从采用 HTTPS 协议的页面请求另一个采用 HTTPS 协议的页面)。如果被请求页面的协议安全等级较低,则不会发送 referrer 首部(比如从采用 HTTPS 协议的页面请求采用 HTTP 协议的页面)。

strict-origin-when-cross-origin: 当发起同源请求时,在 referrer 首部中包含完整的 URL。当被请求页面与来源页面不同源但是有相同协议安全等级时(比如 HTTPS→HTTPS),在 referrer 首部中仅包含来源页面的源。当被请求页面的协议安全等级较低时(比如 HTTPS→HTTP),不发送 referrer 首部。

unsafe-url: 始终在 referrer 首部中包含源以及路径 (但不包括 fragment,密码,或用户名)。这个值是不安全的, 因为这样做会暴露受 TLS 保护的资源的源和路径信息。


不添加referrerpolicy

<iframe name="myIframe" src="https://juejin.cn/" width="500" height="200" />

可以在请求中看到referrer的来源:

image.jpeg


no-referrer

将referrerpolicy的值设置为no-referrer

<iframe name="myIframe" src="https://juejin.cn/" width="500" height="200" referrerpolicy="no-referrer" />

我们在请求中会看不到referrer的来源:

image.jpeg


origin

将referrerpolicy的值设置为origin

<iframe name="myIframe" src="https://juejin.cn/" width="500" height="200" referrerpolicy="origin" />

可以在请求中看到referrer的来源:

image.jpeg


origin-when-cross-origin

将referrerpolicy的值设置为origin-when-cross-origin

<iframe name="myIframe" src="https://juejin.cn/" width="500" height="200" referrerpolicy="origin-when-cross-origin" />

非同源请求的referrer的来源:

image.jpeg


same-origin

将referrerpolicy的值设置为same-origin