iframe中无法访问 Cookie & Session 問題

在 Safari 使用 iFrame 方式嵌入 Cross Domain 页面,会发生 iFrame 无法使用 Cookie,导致每次的 Request 携带的 Session id 都不一样或者登陆信息缺失。
虽然通过改变 Safari 的安全性设置可以解决此问题,但是要让用户修改设置非常困难。我们可以通过 JavaScript 来巧妙地解决该问题。

本文参考 https://blog.johnwu.cc/article/cookie-session-not-working-in-iframe.html

场景

我们接入第三方页面的时候,通常是通过 iFrame 方式进行嵌入。有些用户在 Safari 浏览器访问的时候,偶尔会发生 Cookie 缺失,导致用户信息缺失的情况。这种情况的根本原因在于 Safari 的安全性设置。如果 iFrame 的 Domain 没有被 Safari 直接存取过,Safari 就不会认可你的 Domain ,不允许存取Cookie。简而言之,就是只要你曾经在网址输入框输过该 Domain,Safari 就会认同你的 domain ,允许存取 Cookie。

方案

我们可以通过 JavaScript 来解决该问题,也即通过重定向的方式,将 Parent 转成 iframe.com,让 Safari 认可 iframe.com 后,再重定向回 parent.com。

判断浏览器

当 iframe.con/index 被打开的时候,先判断浏览器,如果是 Safari,我們就将 window.top 设置成 iframe.com/redirect

1
2
3
4
5
6
7
8
9
/* iframe.con/index */  

var userAgent = navigator.userAgent.toLowerCase();
var isSafari = userAgent.indexOf("safari") != -1 && userAgent.indexOf("chrome") == -1;
var hasCookiePermission = document.cookie.indexOf("hasCookiePermission=true") != -1;

if (isSafari && !hasCookiePermission) {
window.top.location = "http://iframe.com/redirect?ref=" + document.referrer;
}

由于 Chrome 的 User Agent 会同时出现 Safari 及 Chrome 字符,因此如果要确保是 Safari,我们需要排除 Chrome 字符。
为了避免无限重定向,当我们获取了 Cookie 存取权限后,就需要停止重定向。

重新轉向到原網址

当 Safari 打开 iframe.com/redirect 时,也就意味着 iframe.com 被认可,可以访问 Cookie 了。因此我们只需要重定向回原來的页面即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/* iframe.com/redirect */  

function getParameterByName(name, url) {
if (!url) {
url = window.location.href;
}
name = name.replace(/[\[\]]/g, "\\$&");
var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
results = regex.exec(url);
if (!results) return null;
if (!results[2]) return "";
return decodeURIComponent(results[2].replace(/\+/g, " "));
}

var ref = getParameterByName("ref");

document.cookie = "hasCookiePermission=true";
window.location = ref;

当我们再度回到 parent.com/home 时,iframe.com 就能正常使用 Cookie 跟 Session 了。