我在后端运行,在http://localhost:4000
前端运行http://localhost:3000
。在服务器(快速)中,我将cors
策略设置为:
app.use( cors({
credentials: true,
origin: "http://localhost:3000",
}));
但是未设置cookie。请求后
POST /graphql HTTP/1.1
Host: localhost:4000
Connection: keep-alive
Content-Length: 373
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36
content-type: application/json
Accept: */*
Origin: http://localhost:3000
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://localhost:3000/register
Accept-Encoding: gzip, deflate, br
Accept-Language: et-EE,et;q=0.9,en-US;q=0.8,en;q=0.7
我返回了带有正确的响应头(?)Set-Cookie
:
HTTP/1.1 200 OK
X-Powered-By: Express
Access-Control-Allow-Origin: http://localhost:3000
Vary: Origin
Access-Control-Allow-Credentials: true
Content-Type: application/json; charset=utf-8
Content-Length: 122
ETag: W/"7a-3NezKfolEhPugNDLsBCed9Xgfzk"
Set-Cookie: lirr=s%3A9JJT7_mt6W-zSWkg-DKkBmxK6O-i8bH3.1k88dMMeintjdSUMV6ig1DK5u4vgdYh4rnmtufww7nw; Path=/; Expires=Sat, 27 Nov 2021 09:31:14 GMT; HttpOnly; SameSite=Lax
Date: Fri, 27 Nov 2020 09:31:14 GMT
Connection: keep-alive
Keep-Alive: timeout=5
我尝试使用Chrome和Firefox,但均未设置Cookie。我的设置没有发现任何缺陷,标题似乎很好。我想念什么?
此外
如果让我从后端设置cookie(公开为Graphql API,可通过Graphql Playground访问),则可以通过以下req头正常工作:
POST /graphql HTTP/1.1
Host: localhost:4000
Connection: keep-alive
Content-Length: 323
accept: */*
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36
content-type: application/json
Origin: http://localhost:4000
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: http://localhost:4000/graphql
Accept-Encoding: gzip, deflate, br
Accept-Language: et-EE,et;q=0.9,en-US;q=0.8,en;q=0.7
据我所知,三行(按预期)有所不同:
Origin: http://localhost:4000
Sec-Fetch-Site: same-origin
Referer: http://localhost:4000/graphql
响应与前端的响应几乎相同:
HTTP/1.1 200 OK
X-Powered-By: Express
Access-Control-Allow-Origin: http://localhost:3000
Vary: Origin
Access-Control-Allow-Credentials: true
Content-Type: application/json; charset=utf-8
Content-Length: 75
ETag: W/"4b-Ud8RJ2O7ZjwpTxFNSAQi92iV20w"
Set-Cookie: lirr=s%3A9CYQjFpVwG69-ojwqlk-FJWVNC02DMJP.Prt8U5%2Bcco9ktEL27JoOkAlACGKS%2Fy1NHfgugPypl00; Path=/; Expires=Sat, 27 Nov 2021 10:32:37 GMT; HttpOnly; SameSite=Lax
Date: Fri, 27 Nov 2020 10:32:37 GMT
Connection: keep-alive
Keep-Alive: timeout=5
我不明白,为什么浏览器没有通过前端设置cookie ...
你的设置对我来说很好。
app.use( cors({
credentials: true,
origin: "http://localhost:3000",
}));
我建议使用一些API工具(例如POSTman)测试你的代码,该工具会默认启用CORS请求。如果它与POSTman一起使用,则你的服务器端代码没有问题。
简而言之,CORS请求不过是到不同域的XMLHttpRequest。https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS
根据以下文档, https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials
此外,此标志还用于指示何时在响应中忽略cookie。默认值为false。来自其他域的XMLHttpRequest不能为自己的域设置cookie值,除非在发出请求之前将withCredentials设置为true。通过将withCredentials设置为true获得的第三方cookie仍将遵循同源策略,因此,请求脚本无法通过document.cookie或从响应标头访问。
除非你启用它,否则浏览器将不会通过CORS request(XMLHttpRequest)接受/传输cookie。
xhr.withCredentials = true;
//from http://localhost:3000
const xhr = new XMLHttpRequest();
const url = 'http://localhost:4000/get-cookie-url';
xhr.open('GET', url);
xhr.withCredentials = true; // enable browser to transfer cookies
xhr.onload = function(e){
console.log(e)
};
xhr.send();
为了说明这一点,cookie的传输类似于握手。
双方都需要发起握手。如果一侧(服务器)启动而另一侧(客户端)未启动,则握手不会发生。
当服务器启动Cookie传输时,
//Server response header
//Server will response with "Set-Cookie" header when browser requests
...
Set-Cookie: lirr=xxxx; ...
...
当客户(浏览器)启动Cookie传输时,
//Client request header
//Client will request with "Cookie" header
...
Cookie: lirr=xxxx; ....
...
通过邮递员,我设置了cookie。好主意,谢谢!接下来,您的链接给了我一些寻找“凭证”客户端的提示。从github.com/benawad/how-to-debug-cookies中,我知道了如何在客户端添加“ withCredentials”。如果我添加,则根据需要设置cookie。但是:我看不到标题中的任何区别,即使在预检中也没有。实际的一半解决了,但是理论上我仍然不清楚。
@wk,干得好,很高兴听到您整理了其中的一些内容。为了说明这一点,Cookie传输与握手非常相似。我将用一些详细信息更新上面的帖子。
我想,在阅读了有关CORS的更多信息后,我很清楚:我使用
urql
的createClient
函数,该函数将JSRequest()
用于HTTP请求。并Request
具有默认的“ same-origin”credentials
。如果我没有将其客户端设置为“ include”,它只会忽略未按原始来源设置的cookie。我假设此信息已包含在标头中,但它们已在客户端进行管理。再次感谢您,您的提示使我找到了解决方案。@wk,太棒了👍,谢谢,您的问题对我来说也很好。自从netscape时代以来,Web浏览器标准已经发生了很大变化。另外,我们的工具/框架在下面也很抽象。因此,有时我们会感到困惑。🤣