0

我在静态服务器(可能是 Amazon S3)上托管了一个单页应用程序网站,因此它是从我的应用程序的 URL 提供的,比如说“example.com”。所以该网站位于“https://example.com”。该站点使用使用 JavaScript 的 fetch() 调用进行的 API 调用来执行站点的功能。因为 example.com 指向一个静态服务器,API 调用会转到不同的域,我们称之为“xyz.execute-api.cloudhost.com”(它恰好位于 Amazon 的 API Gateway 后面)。

我想使用 cookie 来管理用户会话。也就是说,我希望一个 API 调用在响应中返回一个 Set-Cookie 标头,该标头将在浏览器上存储一个 cookie,并且我希望某些其他 API 调用在请求上传递一个 Cookie 标头,然后可以在 API 中对其进行验证。cookie 将始终来自 API 并返回到 API(不是页面的站点,因为页面本身托管在静态服务器上)。我希望在会话之间保存 cookie(具有一些到期生命周期并理解浏览器可能会由于空间限制或用户操作而清除它)。

但这很难做到。首先,我的 API 调用都是到一个单独的域,所以我必须使用 CORS 来授权调用。当我使用 CORS 时,服务器必须在 Access-Control-Allow-Headers 列表中包含“Cookie”,否则将不会返回。此外,当我使用 Javascript 的 fetch() API 进行调用时,我需要指定包含这样的凭据:

fetch(url, {method: "POST", credentials: "include"})

...否则 cookie 将不会被发送。返回 cookie 的 API 调用不需要接收 cookie,但我也必须credentials: "include"为此指定,否则浏览器将忽略该 Set-Cookie 响应标头。

我还需要正确配置 cookie 本身。各种 API 调用有不同的路径,所以我需要Path=/在我的 Set-Cookie 标头中指定。我更喜欢设置SameSite=Strict、和 的值,但如果需要Secure,我愿意灵活处理。HttpOnlyMax-Age

这就是我所得到的。我仍然无法让我的 cookie 被放置(使用 Set-Cookie)并以跨平台的方式返回到服务器(在 Cookie 中)。因为页面域与 API 域不同,我可能需要指定SameSite=None,但如果我这样做,最近的标准更改可能还需要我设置Secure(这很好)。即便如此,我也无法让所有主流浏览器都返回 cookie。我还希望使用相同的密钥设置一个新的 cookie 会替换现有的,但我也无法让它工作——当它返回时,我看到两个 cookie。

在这种情况下使用 cookie 的正确方法是什么?

4

1 回答 1

1

正如您特别提到的,您希望从单独的站点向 API 站点发起这些请求,这意味着它们本质上是跨站点或第三方请求,因此 cookie必须标记为SameSite=None; Secure.

如果您想使用类似的东西SameSite=StrictSameSite=Lax那么您将需要从 SPA 中管理 cookie。这可能更可取,因为它允许您将会话标识符或令牌存储在那里,然后将其作为单独的字段或标头传递给您的 API。这种方式你的 API 不依赖于 cookie,这可能是更可取的。

于 2020-04-07T09:51:29.820 回答