为什么 Chrome 无法设置 cookie

新手上路,请多包涵

我的服务器有回复。响应标头包含有效的 Set-Cookie。 Chrome Response/Cookies 说我有 1 个 cookie,好的。但是…… cookie 没有设置到 DevTools/Application/Cookies

 /*
 My frontend on Vue
 I renamed 127.0.0.1 to www.example.com
 So running on www.example.com:80 or just www.example.com
*/
let response = await axios({
               method: 'post',
               url: 'http://127.0.0.1:3000/api/login', // my Node server on 3000 port
               data: {
                   email : login,
                   password: password,
               },
            })

 /*
 My backend part on Node.js+Express
 Running on localhost:3000 or 127.0.0.1:3000
 CookieParser() is setted
*/
let options = {
              maxAge: 345600000,
              httpOnly: true,
              path: '/',
            }

res
   .cookie('test', 'test', options)
   .cookie('access_token', token, options) //token contains a JWT string
   .send('');

 /*
 Chrome Response Headers
*/
Access-Control-Allow-Origin: *
Connection: keep-alive
Content-Length: 0
Content-Type: text/html; charset=utf-8
Date: Sun, 09 Feb 2020 08:52:22 GMT
ETag: W/"0-2jmj7l5rSw0yVb/vlWAYkK/YBwk"
Set-Cookie: test=test; Max-Age=345600; Path=/; Expires=Thu, 13 Feb 2020 08:52:22 GMT; HttpOnly
Set-Cookie: access_token=example; Max-Age=345600; Path=/; Expires=Thu, 13 Feb 2020 08:52:22 GMT; HttpOnly
X-Powered-By: Express

 /*
 Chrome request headers
*/
Accept: application/json, text/plain, '*/*'
Accept-Encoding: gzip, deflate, br
Accept-Language: ru-RU,ru;q=0.9
Cache-Control: no-cache
Connection: keep-alive
Content-Length: 45
Content-Type: application/json;charset=UTF-8
Host: 127.0.0.1:3000
Origin: http://www.example.com
Pragma: no-cache
Referer: http://www.example.com/
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36

此外,我尝试使用 Microsoft Edge,但问题并没有消失。考虑到浏览器知道接收 Cookie,为什么不能设置 cookie?

原文由 professrr 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 824
2 个回答

如果您想阅读一些背景知识,那么我建议您查找 CORS(跨源资源共享)指南,特别是如何在使用 CORS 时设置 cookie。

使用您的原始代码,您需要将其更改为将 withCredentials 设置为 true

 let response = await axios({
    method: 'post',
    url: 'http://127.0.0.1:3000/api/login', // my Node server on 3000 port
    data: {
        email : login,
        password: password,
    },
    withCredentials: true
})

在幕后,这将在 --- 上设置 XMLHttpRequest withCredentials 标志:

https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials

然后,您将在控制台中收到 CORS 错误。如果您按照自己的方式解决了这些错误,您应该能够使其正常工作。这些错误将包括…

首先,服务器需要返回标头 Access-Control-Allow-Credentials: true 。这也适用于预检 OPTIONS 请求。

其次,您目前正在使用 Access-Control-Allow-Origin: * 但不允许使用凭据的请求。那需要是 Access-Control-Allow-Origin: http://www.example.com 。预检也是如此。

那时应该在大多数浏览器中设置 cookie(稍后将详细介绍浏览器的怪癖)。

要将 cookie 添加到后续请求,您还需要在这些请求上设置 withCredentials: true 。还需要应用上面概述的其他标题更改。 cookie 不会包含在预检请求中,仅包含在主请求中。

在浏览器的开发人员工具中查看 cookie 并不完全简单。通常,这些工具只显示为与当前页面相同的来源设置的 cookie,不包括通过 CORS 请求设置的 cookie。要查看这些 cookie,您需要打开另一个浏览器选项卡并将 URL 设置为以与 CORS 请求相同的来源开头的内容。不过要小心,您需要选择一个不会自己设置 cookie 的 URL,否则它并不能真正证明任何事情。

检查设置了哪些 cookie 的另一种方法是发送另一个请求(使用 withCredentials )并查看发送了哪些 cookie。

然后我们有特定于浏览器的问题……

在 Safari 中,很难通过 CORS 设置 cookie。如果 Safari 是您的目标浏览器,那么我建议对此做一些进一步的研究。

其次,Chrome 80 将显着改变 CORS cookies 的规则。看:

https://www.chromium.org/updates/same-site

使用旧版 Chrome 时,您已经在控制台中看到了有关此的警告。简而言之,需要通过 https 提供 CORS cookie,并设置指令 SecureSameSite=None

更新:

自从写下这个答案以来,我已经为常见的 CORS 问题创建了一个常见问题解答。可以在 https://cors-errors.info/faq#cdc8 找到解释 cookie 使用的部分。

原文由 skirtle 发布,翻译遵循 CC BY-SA 4.0 许可协议

如果您使用 Axios 或 Fetch - 默认情况下它们不会发送 cookie。如果您去查看 dav 工具 -(应用程序选项卡 -> cookie),您应该会看到它们。这不是 chrome 的问题,而是你试图将它们发回的方式,在 fetch 中你需要将 credentials: 'include', 添加到选项对象中,在 axios 中它是 {withCredentials: true}

原文由 Yosi Leibman 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题