cross-domain 请求中的 httpOnly cookie 未发送
httpOnly cookies in cross-domain requests not being sent
我真的很抱歉又问了一个 CORS 问题,但我卡住了,我不明白为什么。
我有任何 API 在登录时以 Set-Cookie
header 响应,它使用我的用户信息设置一个 cookie。该响应如下所示:
来自api.somesite.com
的回应
Access-Control-Allow-Credentials: true
Connection: keep-alive
Content-Length: 183
Content-Type: text/html; charset=utf-8
Date: Mon, 19 Apr 2021 19:55:02 GMT
Set-Cookie: socialAccesstoken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6Ijk5MDk3NzQzNjkxNjU1MTY4MCIsInVzZXJuYW1lIjoiY3JlYXRpdmlpaSIsImRpc3BsYXlOYW1lIjoiTGVvIDjvuI_ig6MiLCJ1cmwiOiJodHRwczovL3QuY28vWjNBM01xaFBDbiIsInBob3RvIjoiaHR0cHM6Ly9wYnMudHdpbWcuY29tL3Byb2ZpbGVfaW1hZ2VzLzEzNzExMzQ3MjY0NzI0MTMxODYvZ0Q5Sk5lVU1fbm9ybWFsLmpwZyIsInByb3ZpZGVyIjoidHdpdHRlciIsImlhdCI6MTYxODg2MjEwMiwiZXhwIjoxNzA1MjYyMTAyfQ.Q7yWf-ywoZ-rWOhYseKTt_0V2_AlEMQ-cCL2rlRNm_U; Max-Age=86400; Path=/; Expires=Tue, 20 Apr 2021 19:55:02 GMT; HttpOnly
Vary: Origin
X-Powered-By: Express
Cookie 设置成功,我可以在 api.somesite.com
的 Application
选项卡中查看它。
然后我尝试从同一域上的页面发出请求:
请求从 somesite.com
到 api.somesite.com
Response
HTTP/1.1 200 OK
X-Powered-By: Express
Access-Control-Allow-Origin: http://somesite.com:8000
Vary: Origin
Access-Control-Allow-Credentials: true
Token-Expired: true
Content-Type: application/json; charset=utf-8
Content-Length: 196
ETag: W/"c4-HQkmHNLuibgvd4gvz0JqjTLKjFU"
Date: Mon, 19 Apr 2021 19:59:18 GMT
Connection: keep-alive
Request
Host: api.somesite.com:3000
Connection: keep-alive
Content-Length: 143
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36
content-type: application/json
Accept: */*
Origin: http://somesite.com:8000
Referer: http://somesite.com:8000/
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Cookie: socialAccesstoken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6Ijk5MDk3NzQzNjkxNjU1MTY4MCIsInVzZXJuYW1lIjoiY3JlYXRpdmlpaSIsImRpc3BsYXlOYW1lIjoiTGVvIDjvuI_ig6MiLCJ1cmwiOiJodHRwczovL3QuY28vWjNBM01xaFBDbiIsInBob3RvIjoiaHR0cHM6Ly9wYnMudHdpbWcuY29tL3Byb2ZpbGVfaW1hZ2VzLzEzNzExMzQ3MjY0NzI0MTMxODYvZ0Q5Sk5lVU1fbm9ybWFsLmpwZyIsInByb3ZpZGVyIjoidHdpdHRlciIsImlhdCI6MTYxODg2MTQ2MiwiZXhwIjoxNzA1MjYxNDYyfQ.BpmQzWWYuBHLQQh6VpatflBsQUv2A0ahLqt1UgYOq8Q
如您所见,cookie 已正确发送。
但是 然后 如果我将我的 api 切换到 api.differentsite.com
并发出相同的请求:
来自api.differentsite.com
的回应
HTTP/1.1 200 OK
X-Powered-By: Express
Vary: Origin
Access-Control-Allow-Credentials: true
Set-Cookie: socialAccesstoken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6Ijk5MDk3NzQzNjkxNjU1MTY4MCIsInVzZXJuYW1lIjoiY3JlYXRpdmlpaSIsImRpc3BsYXlOYW1lIjoiTGVvIDjvuI_ig6MiLCJ1cmwiOiJodHRwczovL3QuY28vWjNBM01xaFBDbiIsInBob3RvIjoiaHR0cHM6Ly9wYnMudHdpbWcuY29tL3Byb2ZpbGVfaW1hZ2VzLzEzNzExMzQ3MjY0NzI0MTMxODYvZ0Q5Sk5lVU1fbm9ybWFsLmpwZyIsInByb3ZpZGVyIjoidHdpdHRlciIsImlhdCI6MTYxODg2MjYzMSwiZXhwIjoxNzA1MjYyNjMxfQ.MvOLarBw_Mz-h26WvOrOqyE0IaDQEnIqp2xLUiFqAZQ; Max-Age=86400; Path=/; Expires=Tue, 20 Apr 2021 20:03:51 GMT; HttpOnly
Content-Type: text/html; charset=utf-8
Content-Length: 183
Date: Mon, 19 Apr 2021 20:03:51 GMT
Connection: keep-alive
(根据 Chrome 中的“应用程序”选项卡,cookie 在 api.differentsite.com:3000
处正确设置)
然后我尝试从 somesite.com
:
发出请求
Response
HTTP/1.1 200 OK
X-Powered-By: Express
Access-Control-Allow-Origin: http://somesite.com:8000
Vary: Origin
Access-Control-Allow-Credentials: true
Content-Type: application/json; charset=utf-8
Content-Length: 147
ETag: W/"93-2hkHY0W/lJkUQBK+JwrKp/OTCro"
Date: Mon, 19 Apr 2021 20:03:26 GMT
Connection: keep-alive
Request
POST /api HTTP/1.1
Host: api.differentsite.com:3000
Connection: keep-alive
Content-Length: 143
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36
content-type: application/json
Accept: */*
Origin: http://somesite.com:8000
Referer: http://somesite.com:8000/
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
没有发送 cookie,因此授权失败。
为什么会这样?这应该有用,不是吗?
我的请求是这样的:
const headers = new Headers();
headers.append("Content-Type", "application/json");
const result = await fetch(endpoint!, {
method: "POST",
headers,
body,
redirect: "follow",
credentials: "include",
}).then((response) => response.json());
我检查了一遍又一遍,确定这些设置是正确的。
我遵循了 上的建议,但没有用。我不确定 Access-Control-Allow-Headers
我应该在我的请求中添加什么。
看来我只需要睡一觉了。
问题是由于我的 cookie 缺少正确的设置造成的。要在 cross-domain
请求中发送 httpOnly cookie,它们需要:
same-site
设置为 none
secure
设置为 true
所以我确保在生产时在 cookie 上设置了这两个值:
sameSite: process.env.NODE_ENV === 'production' ? 'none' : 'lax',
secure: process.env.NODE_ENV === 'production' ? true : false,
它开始工作了。
编辑:
虽然这是正确答案,但似乎 Safari 现在默认会阻止第三方 cookie,这意味着如果客户端是 safari,则不会发送任何 cookie。这可以在设置中停用,但默认情况下处于启用状态。
我真的很抱歉又问了一个 CORS 问题,但我卡住了,我不明白为什么。
我有任何 API 在登录时以 Set-Cookie
header 响应,它使用我的用户信息设置一个 cookie。该响应如下所示:
来自api.somesite.com
Access-Control-Allow-Credentials: true
Connection: keep-alive
Content-Length: 183
Content-Type: text/html; charset=utf-8
Date: Mon, 19 Apr 2021 19:55:02 GMT
Set-Cookie: socialAccesstoken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6Ijk5MDk3NzQzNjkxNjU1MTY4MCIsInVzZXJuYW1lIjoiY3JlYXRpdmlpaSIsImRpc3BsYXlOYW1lIjoiTGVvIDjvuI_ig6MiLCJ1cmwiOiJodHRwczovL3QuY28vWjNBM01xaFBDbiIsInBob3RvIjoiaHR0cHM6Ly9wYnMudHdpbWcuY29tL3Byb2ZpbGVfaW1hZ2VzLzEzNzExMzQ3MjY0NzI0MTMxODYvZ0Q5Sk5lVU1fbm9ybWFsLmpwZyIsInByb3ZpZGVyIjoidHdpdHRlciIsImlhdCI6MTYxODg2MjEwMiwiZXhwIjoxNzA1MjYyMTAyfQ.Q7yWf-ywoZ-rWOhYseKTt_0V2_AlEMQ-cCL2rlRNm_U; Max-Age=86400; Path=/; Expires=Tue, 20 Apr 2021 19:55:02 GMT; HttpOnly
Vary: Origin
X-Powered-By: Express
Cookie 设置成功,我可以在 api.somesite.com
的 Application
选项卡中查看它。
然后我尝试从同一域上的页面发出请求:
请求从 somesite.com
到 api.somesite.com
Response
HTTP/1.1 200 OK
X-Powered-By: Express
Access-Control-Allow-Origin: http://somesite.com:8000
Vary: Origin
Access-Control-Allow-Credentials: true
Token-Expired: true
Content-Type: application/json; charset=utf-8
Content-Length: 196
ETag: W/"c4-HQkmHNLuibgvd4gvz0JqjTLKjFU"
Date: Mon, 19 Apr 2021 19:59:18 GMT
Connection: keep-alive
Request
Host: api.somesite.com:3000
Connection: keep-alive
Content-Length: 143
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36
content-type: application/json
Accept: */*
Origin: http://somesite.com:8000
Referer: http://somesite.com:8000/
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Cookie: socialAccesstoken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6Ijk5MDk3NzQzNjkxNjU1MTY4MCIsInVzZXJuYW1lIjoiY3JlYXRpdmlpaSIsImRpc3BsYXlOYW1lIjoiTGVvIDjvuI_ig6MiLCJ1cmwiOiJodHRwczovL3QuY28vWjNBM01xaFBDbiIsInBob3RvIjoiaHR0cHM6Ly9wYnMudHdpbWcuY29tL3Byb2ZpbGVfaW1hZ2VzLzEzNzExMzQ3MjY0NzI0MTMxODYvZ0Q5Sk5lVU1fbm9ybWFsLmpwZyIsInByb3ZpZGVyIjoidHdpdHRlciIsImlhdCI6MTYxODg2MTQ2MiwiZXhwIjoxNzA1MjYxNDYyfQ.BpmQzWWYuBHLQQh6VpatflBsQUv2A0ahLqt1UgYOq8Q
如您所见,cookie 已正确发送。
但是 然后 如果我将我的 api 切换到 api.differentsite.com
并发出相同的请求:
来自api.differentsite.com
HTTP/1.1 200 OK
X-Powered-By: Express
Vary: Origin
Access-Control-Allow-Credentials: true
Set-Cookie: socialAccesstoken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6Ijk5MDk3NzQzNjkxNjU1MTY4MCIsInVzZXJuYW1lIjoiY3JlYXRpdmlpaSIsImRpc3BsYXlOYW1lIjoiTGVvIDjvuI_ig6MiLCJ1cmwiOiJodHRwczovL3QuY28vWjNBM01xaFBDbiIsInBob3RvIjoiaHR0cHM6Ly9wYnMudHdpbWcuY29tL3Byb2ZpbGVfaW1hZ2VzLzEzNzExMzQ3MjY0NzI0MTMxODYvZ0Q5Sk5lVU1fbm9ybWFsLmpwZyIsInByb3ZpZGVyIjoidHdpdHRlciIsImlhdCI6MTYxODg2MjYzMSwiZXhwIjoxNzA1MjYyNjMxfQ.MvOLarBw_Mz-h26WvOrOqyE0IaDQEnIqp2xLUiFqAZQ; Max-Age=86400; Path=/; Expires=Tue, 20 Apr 2021 20:03:51 GMT; HttpOnly
Content-Type: text/html; charset=utf-8
Content-Length: 183
Date: Mon, 19 Apr 2021 20:03:51 GMT
Connection: keep-alive
(根据 Chrome 中的“应用程序”选项卡,cookie 在 api.differentsite.com:3000
处正确设置)
然后我尝试从 somesite.com
:
Response
HTTP/1.1 200 OK
X-Powered-By: Express
Access-Control-Allow-Origin: http://somesite.com:8000
Vary: Origin
Access-Control-Allow-Credentials: true
Content-Type: application/json; charset=utf-8
Content-Length: 147
ETag: W/"93-2hkHY0W/lJkUQBK+JwrKp/OTCro"
Date: Mon, 19 Apr 2021 20:03:26 GMT
Connection: keep-alive
Request
POST /api HTTP/1.1
Host: api.differentsite.com:3000
Connection: keep-alive
Content-Length: 143
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36
content-type: application/json
Accept: */*
Origin: http://somesite.com:8000
Referer: http://somesite.com:8000/
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
没有发送 cookie,因此授权失败。
为什么会这样?这应该有用,不是吗?
我的请求是这样的:
const headers = new Headers();
headers.append("Content-Type", "application/json");
const result = await fetch(endpoint!, {
method: "POST",
headers,
body,
redirect: "follow",
credentials: "include",
}).then((response) => response.json());
我检查了一遍又一遍,确定这些设置是正确的。
我遵循了 Access-Control-Allow-Headers
我应该在我的请求中添加什么。
看来我只需要睡一觉了。
问题是由于我的 cookie 缺少正确的设置造成的。要在 cross-domain
请求中发送 httpOnly cookie,它们需要:
same-site
设置为none
secure
设置为true
所以我确保在生产时在 cookie 上设置了这两个值:
sameSite: process.env.NODE_ENV === 'production' ? 'none' : 'lax',
secure: process.env.NODE_ENV === 'production' ? true : false,
它开始工作了。
编辑:
虽然这是正确答案,但似乎 Safari 现在默认会阻止第三方 cookie,这意味着如果客户端是 safari,则不会发送任何 cookie。这可以在设置中停用,但默认情况下处于启用状态。