我正试图在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所需满足的条件
- 客户端使用
credentials: 'include'
异步初始化获取请求。有关详细信息,请参见[此处][1]- 要执行CORS,服务器响应标头必须包含显式设置为域的
Access-Control-Allow-Origin
,该域可能与服务器域不同。例如,在单页应用程序体系结构中,您的前端站点临时托管在localhost:3000,后端服务器托管在localhost:8000,那么标头应该是Access-Control-Allow-Origin: http://localhost:3000
。请参见[此处][2]和[此处][3]- 为了允许客户端处理cookie(这显然是一种敏感资源(,服务器响应标头必须进一步包含
Access-Control-Allow-Credentials: true
。请参见[此处][4]。请注意,这将强制执行Access-Control-Allow-Origin
的非通配符设置。参见[here][6]-这就是为什么在上面的第2点中,它必须显式地设置为类似http://localhost:3000
的值,而不是*
- 当服务器设置cookie时,它必须包含
SameSite=None; Secure; HttpOnly
。所以总的来说,像Set-Cookie: session_id=12345; SameSite=None; Secure; HttpOnly
。在最新的浏览器中,SameSite
似乎是一个相对较新的要求[5],当SameSite
设置为None
时,必须与Secure
一起使用- 关于
HttpOnly
,我还没有找到相关的材料,但在我的实验中,省略它会导致浏览器忽略Set-Cookie
标头- 对后端服务器的进一步请求也必须设置
Path
0
来源:https://stackoverflow.com/a/67001424/368691
在CORS模式下,Cookie通常不应附加到飞行前请求。你可能想看看这个。
注意:无论此设置如何,浏览器都不应在飞行前请求中发送凭据。有关更多信息,请参阅:CORS>具有凭据的请求。
https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch