【发布时间】:2020-04-30 13:06:33
【问题描述】:
Safari 不允许您在与父域不同的域的 iframe 中设置 cookie,该死的服务器端 CORS 标头。
澄清一下:用户在 domainA.com 上。 domainB.com 的 iframe 已打开, 并尝试在 domainB.com 内对用户进行身份验证 框架。 Set-Cookie 标头从 domainB.com iframe 内的服务器返回,包含所有必需的标头,但 Safari 不会在后续调用中将其发回。
一个旧的解决方法是从 iframe 提交表单,并在响应中设置 cookie。我猜他们喜欢用户点击某些东西来提交表单的事实。您必须轮询 cookie 以查看响应何时返回,因为表单提交没有回调,并且在 HttpOnly cookie 的情况下您不能,但是嘿,它起作用了!直到没有。
然后,最近的解决方法是将用户重定向到全新窗口/标签中的 iframe 域,在那里设置一个随机 cookie,从那一刻起,该子域在 iframe 中是“受信任的”。同样,它需要单击才能打开新的窗口/标签,甚至还有新标签打开的视觉指示。很多安全性,这样的标准。
现在,从 Safari 13 开始 - 不再有解决方法。没有更安全的 iframe cookie 设置 ????
任何其他身份验证方案都不适合我们(例如 Auth-X 标头)。我们需要使用 HttpOnly 安全 cookie,因为我们不希望 javascript 客户端以任何方式访问该令牌。
需要明确的是,在任何其他浏览器上一切都很好。
有人有什么建议吗?
编辑:
感谢@tomschmidt 的链接,这似乎是正确的方向。 我尝试使用 Apple 的 Storage Access API,但不幸的是,虽然我确保在使用 API 初始化我的登录逻辑之前请求访问:
requestStorageAccess = async() => {
return new Promise(resolve => {
//@ts-ignore
document.requestStorageAccess().then(
function () {
console.log('Storage access was granted');
resolve(true);
},
function () {
console.log('Storage access was denied');
resolve(false);
}
);
});
}
const storageAccessGranted = await requestStorageAccess();
console.log(storageAccessGranted) // prints 'true'
await login();
不过,在 /login API 响应中收到的 cookie 不会在随后的 API 调用中发送:(
编辑 2(2021 年 5 月):
Safari 14 添加了另一个重大变化:
https://webkit.org/blog/11545/updates-to-the-storage-access-api/
去苹果去吧!你让我们想起了 IE6。
【问题讨论】:
-
确保仅在与 iframe 进行显式交互时触发,例如 onclick。
-
是的,我就是这样做的。查看我链接到的 webkit bugzilla 问题,我猜这是 Safari 端的实际错误:/
-
问题不在于没有发送cookies。如果您请求存储访问,现有的 cookie 将发送到服务器。问题是根本没有存储任何新的 cookie,因此它们不会被发送。
-
@MattCosentino 是的,这就是我的意思 - “在 /login API 响应中收到的 cookie”是在 Set-Cookie 标头响应中发送回 iframe 域的新 cookie,但下一次调用来自 iframe 域的请求中不包含这些 cookie。所以是的,更正确的说法是问题的根源是在这种情况下没有新的 cookie 存储在浏览器中。
-
在最近的更改之后如何解决这个问题有什么想法吗?我浏览了您共享的链接,但是当我使用 document.hasStorageAccess() 时,我的浏览器抱怨它不是一个函数。
标签: javascript cookies iframe safari cors