Safari 在另一台服务器上调用 API 时拒绝 Cookie

Posted

技术标签:

【中文标题】Safari 在另一台服务器上调用 API 时拒绝 Cookie【英文标题】:Safari is Rejecting Cookies When Calling An API On Another Server 【发布时间】:2020-05-15 03:32:45 【问题描述】:

我的业务有一个 React 应用程序,它有多个客户端。我的架构是这样设置的:

服务器 A - 主应用服务器,仅服务于 React 应用 (url = https://example.net)

服务器 B - 业务客户端 #1,服务于他们稍微定制的 React 应用程序 (url = https://example2.net)

服务器 C - 业务客户端 #2,服务于他们稍微定制的 React 应用程序 (url = https://example3.net)

微服务服务器 - 运行 Java 微服务(url = https://api.example.net - 注意它是服务器 A 的子域)

服务器 A、B 和 C 都在与微服务服务器进行 API 调用。 API 调用使用带有这些选项的本机浏览器 fetch() 调用

var options = 
   method: "method",
   mode: "cors",
   credentials: "include",
   headers:  "Content-Type": "application/json" 

服务器响应有这个头:

"Access-Control-Allow-Credentials", "true"

并使用微服务的内置

enableCorsForAllOrigins()

现在,这一切都可以在 Firefox、Chrome、IE 和 Edge 上正常运行。但是,它不适用于服务器 B 或服务器 C 的 Safari(MacOS 或 iPhone)。它在服务器 A 上的 Safari 上运行良好。

API 调用按此顺序...

发布https://api.example.net/login

获取https://api.example.net/users

在 Safari 上,第一次调用成功,但第二次调用失败并出现 401 错误。尝试获取“currentUserId”的 Session 属性的微服务抛出 401 错误,该属性为空。换句话说,Safari 不会将 cookie 发送到服务器。我发现 Safari 不喜欢 API 调用转到与客户端服务器不同的 URL 库。 (换句话说,服务器 B 对服务器 A 进行 API 调用)。

为了进一步验证这一点,如果用户在服务器 B 上启动,然后导航到服务器 A 并进行 API 调用(例如登录错误),然后返回到服务器 B,那么它在 Safari 上对他们有效。看起来 Safari 只需要在服务器 A URL 上交换一个 cookie 就可以让它在其他所有服务器上工作。

现在,我的问题...我该如何解决?服务器 B 和服务器 C 上的 Mac Safari 和 iPhone Safari 上的用户无法使用该应用程序,因为他们的会话 cookie 未发送到服务器。有没有人见过这个?有没有人有解决方案?我的第一次尝试是在服务器 B 上创建一个 iframe 来加载服务器 A 的页面,但这没有用。

非常感谢!

【问题讨论】:

可能是由"sameSite" cookies(以及相关的bug in Safari)引起的。 【参考方案1】:

因此,在阅读了上面@str 提供的链接并阅读了这些链接中的链接后,我得出的结论是,尝试使用 cookie 和会话使其工作不适用于 Safari。所以我放弃了整个设置,转而使用 JWT。

所以,我现在的解决方案是:

POST https://api.example.net/login -> 响应包含服务器生成的 JWT 令牌,其中包含 userId。

javascript 代码现在将此 JWT 保存到 SessionStorage(不是 cookie,否则您会遇到与使用 Session 时相同的问题)。

window.sessionStorage.setItem("jwtToken", data.jwtToken);

设置 API 调用以始终将 JWT 令牌作为标头传递。

"Authorization": "Bearer " + window.sessionStorage.getItem("jwtToken")

然后,使用服务器端库,我可以提取 JWT 令牌并从中获取 userId。

它适用于 Safari,是当今 Web 授权的首选解决方案,所以我会说使用这个解决方案。缺点是将 JWT 存储在 sessionStorage 中会使用户容易受到 XSS 攻击。

【讨论】:

"[...] 尝试使用 cookie 和会话使其工作无法与 Safari 一起工作" – 这不是真的。当然,cookie 可以与 Safari 一起使用。但根据您的设置和您测试的 Safari 版本,您必须稍作调整。 "it" = 跨站点 API 调用

以上是关于Safari 在另一台服务器上调用 API 时拒绝 Cookie的主要内容,如果未能解决你的问题,请参考以下文章

开发机器上的网络核心 Web api 应用程序上的 Kestrel 错误,但在另一台机器上却没有

尝试在另一台服务器上调用 EJB 方法时出现 Websphere 错误

如何通过 REST API 在另一台服务器上为 Sharepoint 2013 和 Sharepoint Online 运行的脚本中更新 SharePoint 列表?

如何从托管在另一台服务器上的 Web 应用程序调用客户端计算机托管的 Wcf 服务?

怎样将mac上的文件共享,在另一台windows电脑上使用?

在另一台服务器上移动 PHP 应用程序时无法访问 MySQL 视图