为什么Chrome无法设置Cookie [英] Why Chrome can’t set cookie

查看:2154
本文介绍了为什么Chrome无法设置Cookie的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a response from my server. Response Headers contains a valid Set-Cookie. Chrome Response/Cookies says that I have 1 cookie, ok. But... The cookie is not setting into 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?

Moreover I tried to use Microsoft Edge, but the problem isn't gone. Why browsers can't set-cookie considering they know about receiving Cookies?

推荐答案

如果您想做一些背景阅读,那我建议您寻找有关CORS(跨域资源共享)的指南,尤其是使用CORS时如何设置cookie。

If you want to do some background reading then I suggest you look for guides to CORS (cross-origin resource sharing) and, specifically, how to set cookies when using CORS.

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

Using your original code you'll need to change it to set withCredentials to 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 上的c $ c>标志:

Behind the scenes this will set the withCredentials flag on XMLHttpRequest:

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

然后在您的控制台中获得CORS错误。如果您设法解决这些错误,则应该能够使其正常工作。这些错误将包括...

You'll then get CORS errors in your console. If you work your way through those errors you should be able to get it working. These errors will include...

首先,服务器将需要返回标头 Access-Control-Allow-Credentials:true

Firstly, the server will need to return the header Access-Control-Allow-Credentials: true. This also applies to the preflight OPTIONS request.

第二,您当前正在使用 Access-Control-Allow-Origin:* ,但是使用凭据的请求不允许这样做。该地址必须为 Access-Control-Allow-Origin:http://www.example.com

Secondly, you're currently using Access-Control-Allow-Origin: * but that isn't allowed for requests using credentials. That'll need to be Access-Control-Allow-Origin: http://www.example.com. Likewise for the preflight.

那时,应在大多数浏览器中设置cookie(稍后将对更多的浏览器进行设置)。

At that point the cookie should be set in most browsers (more on browser quirks later).

要将Cookie添加到后续请求中,您还需要在这些请求上设置 withCredentials:true 。上面概述的其他标头更改也需要应用。 Cookie不会包含在飞行前请求中,而不会包含在主要请求中。

To get the cookies added to subsequent requests you'll also need to set withCredentials: true on those requests. The other header changes outlined above also need to be applied. The cookies will not be included on the preflight request, just the main request.

在浏览器的开发人员工具中查看Cookie并非一帆风顺。通常,这些工具只显示与当前页面具有相同来源的cookie,不包括通过CORS请求设置的cookie。要查看这些Cookie,您需要打开另一个浏览器标签,并将URL设置为与CORS请求具有相同来源的开头。不过请注意,您需要选择一个不会自行设置Cookie的URL,否则并不能真正证明任何内容。

Seeing the cookies in the browser's developer tools is not completely straightforward. Generally the tools only show cookies set for the same origin as the current page, which doesn't include the cookies set via CORS requests. To see those cookies you'll need to open another browser tab and set the URL to something that starts with the same origin as the CORS request. Be careful though, you need to pick a URL that won't set the cookies itself, otherwise that doesn't really prove anything.

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

Another way to check what cookies are set is to send another request (with withCredentials) and see what cookies get sent.

然后我们有了浏览器特定问题...

Then we have the browser-specific issues...

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

In Safari it is really difficult to get cookies to set over CORS. If Safari is a target browser for you then I suggest doing some further research into that.

第二,Chrome 80将大大改变有关CORS Cookie的规则。请参阅:

Secondly, Chrome 80 is due to change the rules around CORS cookies significantly. See:

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

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

You'll already see warnings about this in your console with older versions of Chrome. In short, CORS cookies will need to be served over https and set the directives Secure and SameSite=None.

这篇关于为什么Chrome无法设置Cookie的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆