当我们在前端页面中使用 window.open()
打开一个新的窗口时,可以通过 window.opener
属性来访问原始窗口对象,以便进行一些操作。但是,在跨域场景下,由于浏览器的安全策略,访问 window.opener
会被禁止。本文将详细介绍如何绕过这种限制。
背景
在 Web 开发中,我们经常需要在不同的域名之间进行页面跳转,比如 OAuth2 认证、第三方支付等场景。通常的做法是,用户在当前网站中点击某个链接或按钮,然后跳转到另一个网站,完成相关操作后再跳回来。为了实现这个功能,我们可以使用 window.open()
方法打开一个新的浏览器窗口,同时还可以设置 opener
属性指向原始窗口对象:
// 在新窗口中打开百度首页 let baiduWindow = window.open('https://www.baidu.com', '_blank'); baiduWindow.opener = window;
通过上面的代码,我们可以在新窗口中打开百度首页,并将 opener
属性设置为原始窗口对象。在新窗口中执行以下代码,就可以获取原始窗口对象:
let openerWindow = window.opener; console.log(openerWindow.location.href);
但是,如果当前网站与百度不在同一个域名下,上述代码将会抛出安全性异常错误。
解决方案
为了绕过 window.opener
的跨域安全性限制,我们可以使用以下几种方法:
方法一:使用中间页面跳转
我们可以通过使用一个中间页面来实现跨域操作。具体做法是,在原始窗口中打开一个新的页面,该页面负责接收从另一个网站传递过来的数据,然后再将数据传递回原始页面。这个中间页面和原始页面都必须位于同一个域名下。
在原始窗口中打开中间页面,并将数据作为参数传递给它:
let url = 'http://example.com/middle.html?data=' + encodeURIComponent(data); window.open(url, '_blank');
在中间页面中获取数据,并将数据传递回原始页面:
let data = decodeURIComponent(location.search.substring(6)); window.opener.postMessage(data, '*'); window.close();
在原始页面中监听消息事件,接收从中间页面传递过来的数据:
window.addEventListener('message', function(event) { console.log(event.data); });
这种方式的优点是简单易懂,缺点是需要额外添加一个中间页面,稍显麻烦。
方法二:使用 iframe 嵌套页面
我们可以将一个网站的内容通过 iframe 的方式嵌入到另一个网站中。由于同源策略的限制,iframe 中的网页无法访问父窗口的对象,但是可以使用 window.postMessage()
方法向父窗口发送消息。
在原始页面中创建一个 iframe,将要跳转的网址设置为 iframe 的 src:
<iframe id="my-iframe" src="http://example.com"></iframe>
在 iframe 中的页面中通过
window.parent.postMessage()
方法向父窗口发送消息:window.parent.postMessage(data, '*');
在原始页面中监听消息事件,接收从 iframe 中传递过来的数据:
window.addEventListener('message', function(event) { console.log(event.data); });
这种方式的优点是相对简单,缺点是需要在原始页面中
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/31342