Javascript fetch 未发送 Cookie Header (CORS)

Javascript fetch is not sending Cookie Header (CORS)

我正在尝试将 Cookie 发送到 javascript 提取 CORS 请求中的 PHP 脚本。请求从 https://sub1.example.com 开始并包含以下选项:

let response = await fetch('https://sub2.example.com/target.php', {
    method: "POST",
    headers: headers,
    body: formData,
    mode: 'cors',
    credentials: 'include',
    cache: 'no-store'
});

对应的PHP脚本设置如下Headers:

header('Access-Control-Allow-Origin: https://www.example.com');
header('Access-Control-Allow-Methods: POST, OPTIONS');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Headers: Origin, Content-Type, Accept, Authorization, X-Request-With, Set-Cookie, Cookie, Bearer');

但是 Cookie Header 没有随请求一起发送。我也试过:

let headers = new Headers();
headers.set('Cookie', document.cookie);

那也没有效果。我到底做错了什么?

我检查了开发工具中的网络选项卡。 PHP 脚本中的 $_COOKIE 也是空的。绝对没有错误。我还可以看到 Cookie Header 是在任何非 CORS fetch 请求中发送的。

编辑:这是其中一个 Cookie 的设置:

Name: PHPSESSID
Path: /
Secure: true
SameSite: none

我无法共享域,因为它不是 public。但是 Cookie 域与请求中的来源具有相同的值 Header(减去 https://)。

编辑 2:更改了提取 URL 以使发生的事情更清楚。

在 CORS 模式下,通常不应将 Cookie 附加到预检请求。你可能想看看这个。

Note: Browsers should not send credentials in preflight requests irrespective of this setting. For more information see: CORS > Requests with credentials.

https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

问题

请注意,取决于

  • cookie 的 Path 属性值,
  • cookie 的 Domain 属性的有效值,
  • cookie 的 Secure 属性值,
  • cookie的有效值SameSite attribute,
  • 请求的发出和目标来源,

cookie 可能附加也可能不附加到请求。与您的案例特别相关的是 Domain 属性;查看 MDN's page on the topic:

The Domain attribute specifies which hosts can receive a cookie. If unspecified, the attribute defaults to the same host that set the cookie, excluding subdomains. If Domain is specified, then subdomains are always included. Therefore, specifying Domain is less restrictive than omitting it. However, it can be helpful when subdomains need to share information about a user.

您在源 https://sub1.example.com:

上按如下方式设置 cookie
Set-Cookie: PHPSESSID=whatever; Path=/; SameSite=None; Secure

因此,该 cookie 将附加到目标来源为 https://sub1.example.com 的(经过认证的)请求,而不会附加到其他请求。

解决方案

如果您希望将您的 cookie 发送到域为 example.com 子域的所有安全来源,您需要将其 Domain 显式设置为 example.com


关于使用 fetch

发送 cookie

Fetch standard specifies a list of forbidden header names; Cookie is one of them. You cannot set a header named Cookie on a request sent with fetch; the standard simply forbids it. If you want to attach existing cookies to a cross-origin request, use the 'include' value for the credentials parameter 传入 fetch 选项。