如何跨起源共享cookie ?更具体地说,如何使用Set-Cookie头结合头Access-Control-Allow-Origin?

以下是对我的情况的解释:

我试图在localhost:3000上托管的web应用程序中为运行在localhost:4000上的API设置一个cookie。

似乎我在浏览器中收到了正确的响应头,但不幸的是,它们没有效果。这些是响应头:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://localhost:3000
Vary: Origin, Accept-Encoding
Set-Cookie: token=0d522ba17e130d6d19eb9c25b7ac58387b798639f81ffe75bd449afbc3cc715d6b038e426adeac3316f0511dc7fae3f7; Max-Age=86400; Domain=localhost:4000; Path=/; Expires=Tue, 19 Sep 2017 21:11:36 GMT; HttpOnly
Content-Type: application/json; charset=utf-8
Content-Length: 180
ETag: W/"b4-VNrmF4xNeHGeLrGehNZTQNwAaUQ"
Date: Mon, 18 Sep 2017 21:11:36 GMT
Connection: keep-alive

此外,当我使用Chrome开发工具的网络选项卡检查流量时,我可以在响应cookie下看到cookie。然而,我不能看到一个cookie被设置在应用程序选项卡下的存储/ cookie。我没有看到任何CORS错误,所以我假设我还遗漏了其他东西。

有什么建议吗?

我更新:

我正在使用React-Redux应用程序中的请求模块向服务器上的/signin端点发出请求。对于服务器,我使用express。

Express服务器:

res.cookie('token', 'xxx-xxx-xxx', { maxAge: 86400000, httpOnly: true, domain: 'localhost:3000' })

在浏览器中请求:

request.post({ uri: '/signin', json: { userName: 'userOne', password: '123456'}}, (err, response, body) => {
    // doing stuff
})

更新二:

我现在像疯狂一样设置请求和响应头,确保它们在请求和响应中都存在。下面是截图。注意标题Access-Control-Allow-Credentials, Access-Control-Allow-Headers, Access-Control-Allow-Methods和Access-Control-Allow-Origin。看看我在Axios的github上发现的问题,我的印象是所有必需的标题现在都设置好了。然而,还是没有运气……


当前回答

皮姆的回答很有帮助。在我的情况下,我必须使用

Expires / Max-Age: "Session"

如果它是一个dateTime,即使它没有过期,它仍然不会将cookie发送到后端:

Expires / Max-Age: "Thu, 21 May 2020 09:00:34 GMT"

希望对以后遇到同样问题的人有所帮助。

其他回答

皮姆的回答很有帮助, 但这是我经历过的一个边缘情况,

在我的情况下,即使我已经在BE中设置了访问控制-允许起源到特定的起源,在FE中,我收到它为*;这是不允许的

问题是,其他人负责网络服务器的设置, 其中,有一个配置来设置Access-Control-*头,这是覆盖我的头集从BE应用程序

唷. .花了一段时间才想明白。

因此,如果您设置的内容与您收到的内容不匹配,请检查您的web服务器配置。

跨工地方法

若要允许通过CORS请求成功接收和发送cookie,请执行以下操作。

后端(服务器)HTTP报头设置:

将HTTP报头Access-Control-Allow-Credentials值设置为true。 确保设置了HTTP标头Access-Control-Allow-Origin和Access-Control-Allow-Headers。不要使用通配符*。当你设置允许的源时,请确保使用包括方案在内的整个源,即http不等同于CORS中的https。

有关在express js中设置CORS的更多信息,请阅读这里的文档。

Cookie设置: 2021年Chrome和Firefox更新时的Cookie设置:

SameSite = band Secure

当执行SameSite=None时,需要设置Secure。查看文档在SameSite和安全的要求。还要注意,Chrome开发工具现在已经改进了过滤和突出显示网络选项卡和应用程序选项卡中的cookie问题。

前端(客户端):设置XMLHttpRequest。凭据标志为true,这可以通过不同的方式实现,这取决于所使用的请求-响应库:

ES6 fetch()这是HTTP的首选方法。使用凭证:'include'。 jQuery 1.5.1用于遗留目的。使用xhrFields: {withCredentials: true}。 axios作为一个流行的NPM库的例子。使用withCredentials: true。

代理方法

避免做跨站点(CORS)的事情。您可以通过代理来实现这一点。只需使用DNS(子域)和/或负载均衡将所有流量发送到相同的顶级域名和路由。对于Nginx来说,这相对来说不太费力。

这种方法与JAMStack完美结合。JAMStack要求API和Webapp代码在设计上完全解耦。越来越多的用户屏蔽第三方cookie。如果API和Webapp可以很容易地在同一台主机上提供服务,第三方问题(跨站点/ CORS)就解决了。在这里或这里阅读有关JAMStack的信息。

旁注

事实证明,如果域名包含端口,Chrome将不会设置cookie。为localhost(没有端口)设置它不是问题。非常感谢Erwin的提示!

这个代码对我有用

在后端

在corsOptions中设置凭据为true:

const corsOptions = {
 credentials: true,
  };

发送请求前设置cookie:

res.cookie('token', 'xxx-xxx-xxx', { 
maxAge: 24*60*60*1000, httpOnly: true, 
SameSite:"None" })

在前端

浏览器请求(使用axios):

axios.post('uri/signin', 
JSON.stringify({ username: 'userOne', 
password: '123456'}),. 
{withCredentials:true})
.the(result 
=>console.log(result?.data))
.catch(err => console.log(err))

皮姆的回答很有帮助。在我的情况下,我必须使用

Expires / Max-Age: "Session"

如果它是一个dateTime,即使它没有过期,它仍然不会将cookie发送到后端:

Expires / Max-Age: "Thu, 21 May 2020 09:00:34 GMT"

希望对以后遇到同样问题的人有所帮助。

这是对上面关于Heroku服务器的CORS cookie的“Lode Michels”的回答,(以及其他云提供商,如AWS)

你的CORS cookie无法设置的原因是因为Heroku剥离了负载均衡器的SSL证书,所以当你试图在服务器上设置“安全”cookie时,它会失败,因为它不再来自安全连接。

您可以显式地指定连接是否安全,而不是cookie模块检查请求。 https://github.com/pillarjs/cookies

用可可豆,加入这个:

ctx.cookies.secure = true;

编辑:我不能直接评论这个答案,因为低于50的声誉