Javascript fetch未发送Cookie标头(CORS)



我正试图在javascript获取CORS请求中向PHP脚本发送Cookie。请求从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脚本设置以下标头:

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标头不会随请求一起发送。我也试过:

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

这也没有任何效果。我到底做错了什么?

我检查了"开发工具"中的"网络"选项卡。此外,PHP脚本中的$_COOKIE为空。绝对没有错误。我还可以看到Cookie标头是在任何非CORSfetch请求中发送的。

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

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

我无法共享域,因为它不是公共的。但Cookie域的值与请求标头中的原始值相同(减去https://(。

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

问题

请注意,根据

  • cookie的CCD_ 4属性的值
  • cookie的CCD_ 5属性的有效值
  • cookie的CCD_ 6属性的值
  • cookie的CCD_ 7属性的有效值
  • 请求的发出和目的地来源

cookie可以附加到请求,也可以不附加到请求。与您的案例特别相关的是Domain属性;查看MDN的页面主题:

Domain属性指定哪些主机可以接收cookie。如果未指定,则该属性默认为设置cookie的同一主机,不包括子域。如果指定了Domain,则始终包括子域。因此,指定Domain比省略它限制性更小。但是,当子域需要共享有关用户的信息时,它会有所帮助。

您在原点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标准指定了一个禁止的标头名称列表;CCD_ 18就是其中之一。不能在使用fetch发送的请求上设置名为Cookie的标头;标准只是禁止它。如果您想将现有cookie附加到跨源请求,请使用fetch选项中传递的credentials参数的'include'值。

这些是浏览器保存并使用fetch:启动的cookie所需满足的条件

  1. 客户端使用credentials: 'include'异步初始化获取请求。有关详细信息,请参见[此处][1]
  2. 要执行CORS,服务器响应标头必须包含显式设置为域的Access-Control-Allow-Origin,该域可能与服务器域不同。例如,在单页应用程序体系结构中,您的前端站点临时托管在localhost:3000,后端服务器托管在localhost:8000,那么标头应该是Access-Control-Allow-Origin: http://localhost:3000。请参见[此处][2]和[此处][3]
  3. 为了允许客户端处理cookie(这显然是一种敏感资源(,服务器响应标头必须进一步包含Access-Control-Allow-Credentials: true。请参见[此处][4]。请注意,这将强制执行Access-Control-Allow-Origin的非通配符设置。参见[here][6]-这就是为什么在上面的第2点中,它必须显式地设置为类似http://localhost:3000的值,而不是*
  4. 当服务器设置cookie时,它必须包含SameSite=None; Secure; HttpOnly。所以总的来说,像Set-Cookie: session_id=12345; SameSite=None; Secure; HttpOnly。在最新的浏览器中,SameSite似乎是一个相对较新的要求[5],当SameSite设置为None时,必须与Secure一起使用
  5. 关于HttpOnly,我还没有找到相关的材料,但在我的实验中,省略它会导致浏览器忽略Set-Cookie标头
  6. 对后端服务器的进一步请求也必须设置Path0

来源:https://stackoverflow.com/a/67001424/368691

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

注意:无论此设置如何,浏览器都不应在飞行前请求中发送凭据。有关更多信息,请参阅:CORS>具有凭据的请求。

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

最新更新