返回
跨域不同标签页打开window.open(),加载成功页面
javascript
2024-03-14 02:13:32
在不同的标签页中打开 window.open()
问题
你正在测试一个第三方 SSO 系统,该系统在一个不同的标签页中运行。成功登录后,你可以以 .php 表单运行任何你想要的脚本。你需要登录脚本在浏览器中打开的一个特定标签页中加载成功页面。
假设你在标签页 1 中访问 acme.com,并单击 APP 上的登录。Acme.com 在新窗口中弹出标签页 2 并执行 SSO。你登录并希望运行一个脚本,在标签页 1 中加载已登录页面,并关闭标签页 2。
解决方案
使用 postMessage
postMessage() 方法允许你跨域发送消息,即使窗口来自不同的域。这使我们能够从 SSO 标签页向主应用程序标签页发送消息,并触发成功页面的加载。
步骤:
1. 在 SSO 标签页中:
- 使用 postMessage() 方法向主应用程序标签页发送一条消息,其中包含成功状态和成功页面的 URL。
- 例如:
window.opener.postMessage({ success: true, url: 'https://example.com/success' }, '*');
2. 在主应用程序标签页中:
- 监听 postMessage() 事件。
- 当收到消息时,加载提供的成功页面。
- 例如:
window.addEventListener('message', (event) => {
if (event.data.success) {
window.location.href = event.data.url;
}
});
关闭标签页
一旦成功页面加载,你可以使用 window.close() 方法关闭 SSO 标签页。
示例代码
SSO 标签页:
window.opener.postMessage({ success: true, url: 'https://example.com/success' }, '*');
window.close();
主应用程序标签页:
window.addEventListener('message', (event) => {
if (event.data.success) {
window.location.href = event.data.url;
}
});
注意
- 确保主应用程序标签页和 SSO 标签页来自同一个域,否则 postMessage() 不会起作用。
- 使用 "*" 作为 postMessage() 的第二个参数,表示消息可以发送到任何窗口。
结论
通过使用 postMessage() 方法,你可以跨域在不同的标签页中打开 window.open(),并加载成功页面。这对于实现第三方 SSO 系统和其他涉及多标签页操作的场景非常有用。
常见问题解答
1. 如果 postMessage() 没有触发主应用程序标签页中的事件,该怎么办?
- 检查主应用程序标签页是否正在监听 postMessage() 事件。
- 检查消息传递的源是否与主应用程序标签页的域相匹配。
- 确保已将 "*" 用作 postMessage() 的第二个参数。
2. 如何关闭 SSO 标签页而不手动调用 window.close()?
- 在主应用程序标签页中,使用 Window.postMessage() 方法向 SSO 标签页发送一条关闭消息。
- 在 SSO 标签页中,监听 Window.postMessage() 事件并根据需要关闭标签页。
3. 如何在不同窗口而不是标签页中打开 window.open()?
- 在 window.open() 的第二个参数中指定 "noopener" 选项。
- 这将创建一个新的窗口,但不会与主应用程序窗口共享任何会话数据。
4. 如何在 iframe 中使用此方法?
- postMessage() 方法也可以在 iframe 和其父窗口之间使用。
- 只需确保 iframe 的源域与父窗口的域匹配即可。
5. 还有其他方法可以在不同的标签页中加载成功页面吗?
- 除了 postMessage(),你还可以使用 Window.location.replace() 方法或 AJAX 来在不同的标签页中加载页面。