gpt4 book ai didi

reactjs - 前后端分离 : Safari not storing cookies from API which is hosted on a separate domain than its Frontend SPA client

转载 作者:行者123 更新时间:2023-12-03 14:12:28 25 4
gpt4 key购买 nike

据我所知,我有一个现在相当常见的设置:一个位于其自己域(例如 myapi.com)上的后端 REST API,以及一个单页前端应用程序这是在其他地方提供的,例如 myapp.com

SPA 是 API 的客户端,API 要求用户在执行操作之前进行身份验证。

后端 API 使用 cookie 来存储某些允许的来源(其中 myapp.com)的 session 数据。这是为了有一个安全的总线来传输和存储身份验证数据,而不必担心客户端。

在 Chrome、Opera 和 Firefox 中,这工作得很好:进行 API 调用来验证用户身份,返回 Cookie 并将其存储在浏览器中,以便与下一次调用一起推送。

另一方面,Safari 确实收到了 cookie,但拒绝存储它们:

Auth call

First call

我怀疑 Safari 将 API 域视为第 3 方 cookie 域,因此阻止存储 cookie。

这是 Safari 中的预期行为吗?如果是这样,有哪些最佳实践可以解决这个问题?

最佳答案

延续 answering your own question 的传统关于这一点。

TL;DR 这是 Safari 中所需的行为。解决这个问题的唯一方法是将用户带到 API 域(问题中的 myapi.com)上托管的网页,并从那里设置一个 cookie - 任何东西,你都可以编写一个小代码如果你愿意的话,可以在 cookies 里放一首诗。

完成此操作后,该域将被列入“白名单”,Safari 会善待您,并在任何后续调用中设置您的 Cookie,即使来自不同域的客户端也是如此。

这意味着您可以保持身份验证逻辑不变,只需引入一个为您设置“种子”cookie 的哑端点。在我的 Ruby 应用程序中,如下所示:

class ServiceController < ActionController::Base
def seed_cookie
cookies[:s] = {value: 42, expires: 1.week, httponly: true} # value can be anything at all
render plain: "Checking your browser"
end
end

客户端,您可能需要检查if the browser making the request is Safari并在打开那个丑陋的弹出窗口后推迟您的登录逻辑:

const doLogin = () => {
if(/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) {
const seedCookie = window.open(`http://myapi.com/seed_cookie`, "s", "width=1, height=1, bottom=0, left=0, toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no")
setTimeout(() => {
seedCookie.close();
// your login logic;
}, 500);
} else {
// your login logic;
}
}

更新:上面的解决方案对于登录用户来说效果很好,即它正确地将当前浏览器 session 的 API 域“列入白名单”。

但不幸的是,用户刷新页面似乎会使浏览器重置为原始状态,其中 API 域的第 3 方 cookie 被阻止。

我发现处理窗口刷新情况的一个好方法是 detect it in javascript页面加载后,将用户重定向到与上面的 API 端点执行相同操作的 API 端点,然后将用户重定向到他们导航到的原始 URL(正在刷新的页面):

if(performance.navigation.type == 1 && /^((?!chrome|android).)*safari/i.test(navigator.userAgent)) {
window.location.replace(`http://myapi.com/redirect_me`);
}

让事情变得复杂的是,如果响应的 HTTP 状态是 30X(重定向),Safari 将不会存储 cookie。因此,Safari 友好的解决方案涉及设置 cookie 并返回 200 响应以及将处理浏览器内重定向的 JS 片段。

就我而言,作为 Rails 应用程序的后端,该端点如下所示:

def redirect_me
cookies[:s] = {value: 42, expires: 1.week, httponly: true}
render body: "<html><head><script>window.location.replace('#{request.referer}');</script></head></html>", status: 200, content_type: 'text/html'
end

关于reactjs - 前后端分离 : Safari not storing cookies from API which is hosted on a separate domain than its Frontend SPA client,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52446840/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com