node.js - 为什么Chrome无法设置Cookie

标签 node.js express vue.js axios postman

我的服务器有回应。响应标题包含有效的Set-Cookie。 Chrome响应/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的知识?

最佳答案

如果您想做一些背景阅读,那么我建议您寻找有关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
})
在幕后,这将在withCredentials上设置XMLHttpRequest标志:
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials
然后,您会在控制台中收到CORS错误。如果您通过这些错误来解决问题,那么您应该能够使其工作。这些错误将包括...
首先,服务器将需要返回 header Access-Control-Allow-Credentials: true。这也适用于印前检查OPTIONS请求。
其次,您当前正在使用Access-Control-Allow-Origin: *,但是使用凭据的请求不允许这样做。那需要是Access-Control-Allow-Origin: http://www.example.com。对于印前检查也是如此。
届时,应该在大多数浏览器中设置cookie(稍后会在浏览器怪癖中提供更多信息)。
要将Cookie添加到后续请求中,您还需要在这些请求上设置withCredentials: true。上面概述的其他 header 更改也需要应用。 Cookie不会包括在预检请求中,而只会包含在主请求中。
在浏览器的开发人员工具中查看cookie并非一帆风顺。通常,这些工具仅显示设置为与当前页面具有相同来源的cookie,但不包括通过CORS请求设置的cookie。要查看这些Cookie,您需要打开另一个浏览器标签,并将URL设置为与CORS请求具有相同来源的开头。不过请注意,您需要选择一个不会设置Cookie本身的URL,否则它并不能证明任何事情。
检查设置了哪些Cookie的另一种方法是发送另一个请求(使用withCredentials),并查看发送了哪些Cookie。
然后,我们遇到了特定于浏览器的问题...
在Safari中,很难通过CORS设置Cookie。如果Safari是适合您的目标浏览器,那么我建议对此做一些进一步的研究。
其次,Chrome 80将大大更改有关CORS Cookie的规则。看:
https://www.chromium.org/updates/same-site
使用较旧版本的Chrome,您已经在控制台中看到有关此问题的警告。简而言之,需要在https上转换CORS Cookie,并设置SecureSameSite=None指令。
更新:
自编写此答案以来,我为常见的CORS问题创建了FAQ。可以在https://cors-errors.info/faq#cdc8中找到有关cookie用法的部分。

关于node.js - 为什么Chrome无法设置Cookie,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60131986/

相关文章:

node.js - express.js 中的路由器优先顺序

javascript - 设置单个单元格样式 js-xlsx, xlsx-style node.js

node.js - MongoDB Node Express GET 和 DELETE 工作,而不是 POST?

laravel - vue SFC 中图像 src 的最佳实践是什么?

javascript - TypeError : vue. openBlock 不是函数,同时使用自定义节点模块中的 vue 组件

javascript - 将 forEach 循环中内置的数组数据写回原始对象

node.js - express 和 grunt 类似吗?有什么不同?与 grunt 相比,express 的优点是什么?

node.js - 如果nodejs中给出了繁忙的时段,如何找到一天中的空闲时段

node.js - Express.js 中的“ session ”未定义

javascript - 检查 req.body 是否为空不适用于express