我有一个在不同域上运行的后端和前端。后端为前端提供了一个API,我可以控制两者。后端向前端发送一个cookie,我希望前端将在进一步的请求上发送回来。 我不需要JavaScript来读取Cookie,我只希望它可以从后端获取并发送回后端。
出于本实验的目的,后端在http://api.localtest.me:8000上运行,前端在http://foo.lvh.me:3000上运行。这两个主机名都解析为127.0.0.1,因为我目前正在自己的开发计算机上运行它们。
服务器发送以下CORS标头:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://foo.lvh.me:3000
允许客户端与服务器对话并接收cookie。完整的请求和响应如下所示:
curl.exe -H "Accept: application/json, text/plain, */*" -H "DNT: 1" -H "Origin: http://foo.lvh.me:3000" -H "Referer: http://foo.lvh.me:3000" -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36" --verbose http://app.localtest.me:8000/api-v1/current-user/
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to app.localtest.me (127.0.0.1) port 8000 (#0)
> GET /api-v1/current-user/ HTTP/1.1
> Host: app.localtest.me:8000
> Accept: application/json, text/plain, */*
> DNT: 1
> Origin: http://foo.lvh.me:3000
> Referer: http://foo.lvh.me:3000
> User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36
>
< HTTP/1.1 200 OK
< Date: Wed, 16 Jan 2019 09:45:37 GMT
< Server: WSGIServer/0.2 CPython/3.7.1
< Content-Type: application/json
< Vary: Accept, Cookie, Origin
< Allow: GET, HEAD, OPTIONS
< X-Frame-Options: SAMEORIGIN
< Content-Length: 2
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Origin: http://foo.lvh.me:3000
< Set-Cookie: sessionid=v04omdilmwz13h1vcirdz8r8pd6r5awv; expires=Wed, 30 Jan 2019 09:45:37 GMT; HttpOnly; Max-Age=1209600; Path=/; SameSite=Lax
<
{}* Connection #0 to host app.localtest.me left intact
服务器很明显正在发送Set-Cookie
。现在,当我在Chrome中执行完全相同的操作时,请求和响应将如下所示:
请注意,缺少Set-Cookie
。那饼干在哪儿吃的?我一步一步调试了后端,然后看到Set-Cookie标头被写入到流向浏览器的流中。
前端使用具有凭据的axios:
axios.get("http://api.localtest.me:8000/api-v1/current-user/", {withCredentials: true}).then(response => { console.log(response) })
response.request
中的请求似乎显示withCredentials
正确设置:
我将对axios的呼叫替换为:
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://api.localtest.me:8000/api-v1/current-user/', true);
xhr.withCredentials = true;
xhr.send(null);
,其行为完全相同。我将withCredentials
更改为false
,并且行为也保持不变。这似乎与withCredentials
is supposed to do(强调我的观点)相反:
XMLHttpRequest.withCredentials属性是一个布尔值, 指示是否应进行跨站点访问控制请求 使用Cookie ,授权标头或TLS之类的凭据进行 客户证书。设置withCredentials不会影响 同一站点的请求。
在Firefox中,情况有所不同。它显示了从服务器发送的cookie,但没有将其发送回(在图中,这不是第一个请求,因此,发送的cookie应该相同):
我再次使用Fiddler确认这些都是请求和响应中的标头:
有什么想法吗?
我尝试从Cookie中删除SameSite: lax
,并且行为相同。
为澄清起见,这些都不是第一个请求,以前的请求应该已经设置了cookie。在这里您可以看到一个接一个的三个请求: