为什么Chrome无法设置Cookie

时间:2020-02-08 22:53:16

标签: node.js express vue.js axios postman

我收到服务器的回应。响应标题包含有效的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?

3 个答案:

答案 0 :(得分:8)

如果您想做一些背景阅读,那么我建议您寻找有关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错误。如果您设法解决这些错误,则应该可以使其正常工作。这些错误将包括...

首先,服务器将需要返回标头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 Cookie的规则。参见:

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

使用较旧版本的Chrome,您已经在控制台中看到有关此问题的警告。简而言之,将需要在https上投放CORS Cookie,并设置伪指令SecureSameSite=None

更新

自编写此答案以来,我为常见的CORS问题创建了FAQ。可以在https://cors-errors.info/faq#cdc8上找到解释Cookie的部分。

答案 1 :(得分:1)

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

答案 2 :(得分:0)

如果您使用 express,可能会使用 express-session 作为您的会话 cookie。

来自官方文档:https://www.npmjs.com/package/express-session


如果您使用 cross-site origin and https 安全连接:

session: {
   cookie: {
      maxAge: 1000*60*60*1,
      httpOnly: true, //set false if you want to change the cookie using JavaScipt
      secure: true,
      sameSite: 'none'
  }
}

并且不要忘记设置: app.set('trust proxy', 1) 使用 express js


否则在 localhost 中你可以使用

session: {
   cookie: {
      maxAge: 1000*60*60*1,
      httpOnly: true, //set false if you want to change the cookie using JavaScipt
      secure: false,
      sameSite: 'lax'
  }
}