在私有浏览器中加载跨域 iframe 会注销用户

Posted

技术标签:

【中文标题】在私有浏览器中加载跨域 iframe 会注销用户【英文标题】:Loading a cross-domain iframe in a private browser logs user out 【发布时间】:2020-08-15 07:58:52 【问题描述】:

我正在与一个客户合作,我在一个子域上制作一个小型专用异地。他们希望我在用户点击按钮时使用他们的 API 发出简单的发布请求,但客户端不希望用户再次登录,而是希望他们使用来自主站点的访问令牌。所以我要求他们的工程师使用访问令牌从我的子域添加对 postMessage 的响应

域结构如下:

站点 1 - https://www.example.com

站点 2 - https://sub.example.com

还有一个非常简单的例子,说明我拥有什么以及他们拥有什么:

//set the src of the iframe
$("#main-site-iframe").attr("src", "https://www.example.com");
//wait for the main site page to open
$("#main-site-iframe")[0].onload = () => 
    //my page posts a message to their site
    $("#my-iframe")[0].contentWindow.postMessage("jwt", "https://www.example.com");  
;
//their site listens for a request
window.addEventListener('message', tokenRequest, false);
function tokenRequest(e) 
    //make sure the request is from the correct subdomain
    if(e.origin == 'https://sub.example.com')
    
        //respond with the access token
        e.source.postMessage(authJWT, e.origin);
    

通常步骤如下:

登录站点 1 按下加载 Site2 的按钮 Site2 加载包含 Site1 的 iframe 由于用户已经登录到 Site1,他们已经登录到 iframe 内的站点 Site2 执行 postMessage 以获取 jwt Site1 以 jwt 响应 一切正常,我们现在有了 jwt,所以我们可以使用 API

在正常情况下,这一切都可以正常工作,但由于某种原因,这在私人浏览器中不起作用。

登录站点 1 按下加载 Site2 的按钮 Site2 加载包含 Site1 的 iframe 加载的 Site1 没有用户登录 Site2 执行 postMessage 并得到 false 响应,因为他们没有登录 我重定向到 Site1 的登录屏幕,因为我认为他们实际上已注销

iframe 的加载不知何故导致用户完全退出(转到另一个选项卡中的主页显示用户实际上已退出)

奇怪的是,这只是第一次在私人窗口中发生,如果用户再次重复前几个步骤,页面第二次正常工作(除非他们关闭私人浏览器并重新开始)所以如果你按照这个,它工作正常

登录站点 1 按下加载 Site2 的按钮 Site2 加载包含 Site1 的 iframe 加载的 Site1 没有用户登录 Site2 执行 postMessage 并得到 false 响应,因为他们没有登录 我重定向到 Site1 的登录屏幕,因为我认为他们实际上已注销 再次登录 Site1 按下加载 Site2 的按钮 Site2 加载包含 Site1 的 iframe 由于用户已经登录到 Site1,他们已经登录到 iframe 内的站点 Site2 执行 postMessage 以获取 jwt Site1 以 jwt 响应 一切正常

postMessage 中是否缺少我不知道的内容或其他内容?提前致谢。

【问题讨论】:

【参考方案1】:

事实证明,这种行为是由 http 与 https 的一些来回引起的。开发服务器没有 ssl 证书,所以它从来不是问题(它总是使用 http),而临时服务器有,但它没有强制执行(所以它可以在 http 和 https 之间切换)这实际上可以在生产中使用生产强制执行 https 它只是在暂存时失败,因为未强制执行 https。

由于浏览器将 http 和 https 视为单独的页面,因此会话令牌不在另一个本地存储中,具体取决于首先登录的页面。它是这样的:

Login to Site1 on https
Press a button that loads Site2 on http
Site2 loads an iframe that has Site1 but in http
Loads Site1 in http does NOT have the user logged in
Site2 does a postMessage and gets a response of false because they are not logged in
Redirect to Site1's Login Screen but this time on http
User logs in again on http not https
Press a button that loads Site2 on http
Loads Site1 in http and DOES have the user logged in this time
Everything works

【讨论】:

以上是关于在私有浏览器中加载跨域 iframe 会注销用户的主要内容,如果未能解决你的问题,请参考以下文章

在 iframe 中跨域加载 Angular UI

调整跨域 iframe 高度的大小 [重复]

在IFrame中使用postMessage跨域

Javascript中开启器上的跨域更新哈希

跨域 iframe 调整大小?

跨域访问和同源策略