iframe 与父页面交互
父页面与 iframe 交互
/**
* 父页面获取 iframe window 对象
*/
const iframeWin = document.getElementById("iframe").contentWindow;
const iframeWin = document.getElementsByTagName('iframe')[0].contentWindow;
/**
* 父页面获取 iframe document 对象
*/
const iframeDoc = iframeWin.document;
/**
* 父页面获取 iframe body 对象
*/
const iframeBody = iframeDoc.body;
/**
* 父页面调用 iframe 方法
*/
iframeWin.method(); // method 是 iframe 的一个方法名
iframe 与父页面交互
/**
* iframe 获取父页面 window 对象
*/
const parentWin = window.parent;
/**
* iframe 获取父页面 document 对象
*/
const parentDoc = window.parent.document;
/**
* iframe 获取父页面 window 对象
*/
const parentBody = window.parent.body;
/**
* iframe 调用父页面的方法
*/
window.parent.method(); // method 是父页面的方法
iframe 与父页面之间传递数据
window.postMessage
是允许两个(跨域)窗口或 iframes 发送数据信息。像是跨域的AJAX,但不是浏览器跟服务器之间交互,而是在两个客户端之间通信。更多信息查看 window.postMessage
发送消息:
/**
* iframe 页面发送消息
*/
const message = 'Hello!'; // 发送到其他 window的数据
const domain = '*'; // 指定哪些窗口能接收到消息事件,‘*’表示无限制
window.postMessage(message, domain);
接收消息:
/**
* data: 发送方窗口发送的数据
* origin: 发送方窗口的 origin
* source: 发送消息的窗口对象的引用
*/
window.addEventListener('message', (event) => {
const { data, origin, source } = event
console.log(event)
}, false);
嵌套多个 ifream 跳转
背景
A, B, C, D 是四个页面,B 是 A 的 iframe,C 是 B 的 iframe,D 是 C 的 iframe。
问题
在 D 中跳转页面
跳转
使用 window.open()
是类似的。
/**
* 在本页面跳转(D 页面跳转)
*/
window.location.href = '';
/**
* 在上一层页面跳转(C 页面跳转)
*/
window.parent.location.href = '';
/**
* 在上上一层页面跳转(B 页面跳转)
*/
window.parent.parent.location.href = '';
/**
* 在最外层页面跳转(A 页面跳转)
*/
window.top.location.href = '';
链接或form
D 页面中有form
/**
* form 提交后,在 D 页面跳转
*/
<form></form>
/**
* form 提交后,弹出新页面
*/
<form target="_blank"></form>
/**
* form提交后,在 C 页面跳转
*/
<form target="_parent"></form>
/**
* form提交后,在 A 页面跳转
*/
<form target="_top"></form>
刷新
/**
* C 页面刷新
*/
window.parent.location.reload();
/**
* A 页面刷新
*/
window.top.location.reload();
Chrome 80 后无法携带 Iframe cookie
前言
从 Chrome 51 开始,浏览器的 HTTP响应头 Set-Cookie
新增加一个 SameSite
属性,该属性默认是关闭的。从 Chrome 80 之后,该属性默认开启。
SameSite SameSite
属性:用来防止 CSRF
攻击和用户追踪。接受以下三个值:
属性值 | 含义 |
---|---|
Strict | 完全禁止第三方 Cookie。Cookies只会在第一方上下文中发送,不会与第三方网站发起的请求一起发送。跨站点时,任何情况下都不会发送 Cookie。 |
Lax | 浏览器中的默认值。Cookies 允许与顶级导航一起发送,并将与第三方网站发起的 GET 请求一起发送。顶级导航到目标网址的 GET 请求,只包括三种情况:链接,预加载请求,GET 表单。iframe 、AJAX 、Image 是不会发送第三方 cookie 的。 |
None | Cookie将在所有上下文中发送,即允许跨域发送。 |
问题描述
在 iframe 中,即使 iframe 页面和 iframe 的服务器不存在跨域问题,但是当 iframe 发出请求时,iframe 的父级页面也就是当前网页的 URL 和请求目标并不同源,所以请求想要携带的 iframe 域下的 cookie 属于第三方 cookie,浏览器默认会禁止其携带。
解决方法
1. 修改浏览器 SameSite 属性【只针对于 Chrome 】
版本 | 修改方法 |
---|---|
Chrome 80 之前 | 未设置SameSite,允许携带第三方 cookie |
Chrome 80 - 90 | 修改浏览器 flags 的两个属性:SameSite by default cookies、Cookies without SameSite must be secure |
Chrome 91 - 93 | 修改浏览器启动参数:SameSiteByDefaultCookies 和 CookiesWithoutSameSiteMustBeSecure |
Chrome 94 | - |
Chrome 80 - 90:
- 谷歌浏览器地址栏输入:
chrome://flags/
- 找到:SameSite by default cookies、Cookies without SameSite must be secure
- 设置这两项为 Disable
Chrome 91之后
浏览器禁用了 flags 的same-site-by-default-cookies
和cookies-without-same-site-must-be-secure
两个属性,所以不能在 flags 修改。但是可以通过修改启动 Chrome 所带的两个参数:SameSiteByDefaultCookies
和CookiesWithoutSameSiteMustBeSecure
来实现携带 cookie。
Windows 系统可以通过修改应用的快捷方式目标属性来给启动的应用加上参数:
- 右击 Chrome 的快捷方式,点击"属性"
- 在"目标(Target)"属性中末尾加上(需要空格):
--disable-features=SameSiteByDefaultCookies,CookiesWithoutSameSiteMustBeSecure
- 重启浏览器(点击此快捷方式)
Mac 系统可以通过终端打开浏览器解决:
- 关闭浏览器
- 打开终端输入命令:
open -a "Google Chrome" --args --disable-features=SameSiteByDefaultCookies,CookiesWithoutSameSiteMustBeSecure
Chrome 94
将会移除--disable-features=SameSiteByDefaultCookies,CookiesWithoutSameSiteMustBeSecure
。
2. 设置 Cookie
报文里面set-cookie,添加SameSite=None; Secure=true。host 必须是 https
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。