无法在 CORS 请求中发送凭据

Posted

技术标签:

【中文标题】无法在 CORS 请求中发送凭据【英文标题】:Unable to send credentials in CORS request 【发布时间】:2017-08-06 22:08:52 【问题描述】:

我有一个应用程序,其中 Vue 前端与服务器位于不同的域中。具体来说,Vue 位于localhost:8080,服务器位于localhost:4000

在成功登录期间,服务器会使用具有会话密钥的 HttpOnly cookie 进行响应。回复如下:

HTTP/1.1 200 OK
server: Cowboy
date: Wed, 15 Mar 2017 22:35:46 GMT
content-length: 59
set-cookie: _myapp_key=SFMyNTY.g3QAAAABbQAAABBndWFyZGlhbl9kZWZhdWx0bQAAAUNleUpoYkdjaU9pSklVelV4TWlJc0luUjVjQ0k2SWtwWFZDSjkuZXlKaGRXUWlPaUpWYzJWeU9qSWlMQ0psZUhBaU9qRTBPVEl5TURrek5EY3NJbWxoZENJNk1UUTRPVFl4TnpNME55d2lhWE56SWpvaVFYTndhWEpsSWl3aWFuUnBJam9pWWpreU5tVmpZek10TVRrM1lTMDBPREkyTFRrek5tSXRaRGxsTURneE5UUTNZVEpsSWl3aWNHVnRJanA3ZlN3aWMzVmlJam9pVlhObGNqb3lJaXdpZEhsd0lqb2lZV05qWlhOekluMC43THdySDUxb1hVVFR3OEhYMzBPWDJTeTd0Si05RTFFZEpQV3ZDLS1WU3YycllpZ29aTUY4NkhUMzB6Q29SWXFBajlxYXFQc0dqTzNNNFJyOHYyY1ZGZw.2k1A4HuW6VV8ACZhgHY6Szuf5gXKAe_QwMCN3doi9D4; path=/; HttpOnly
content-type: application/json; charset=utf-8
cache-control: max-age=0, private, must-revalidate
x-request-id: qi2q2rtt7mpi9u9c703tp7idmfg4qs6o
access-control-allow-origin: http://localhost:8080
access-control-expose-headers: 
access-control-allow-credentials: true
vary: Origin

但是,使用 Vue 资源发出的后续请求不会将此 cookie 发送回服务器,即使我包含了 credentials: true 选项:

this.$http.get("http://localhost:4000/api/account/", credentials: true).then(response => 
  //do stuff
, response => 
  console.log(response.body.error)
)

我知道不包含凭据,因为我可以在 Chrome 中看到请求标头:

GET /api/account/ HTTP/1.1
Host: localhost:4000
Connection: keep-alive
Accept: application/json
Origin: http://localhost:8080
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/56.0.2924.87 Safari/537.36
Referer: http://localhost:8080/
Accept-Encoding: gzip, deflate, sdch, br
Accept-Language: en-US,en;q=0.8,tr;q=0.6

因此,我从服务器收到 401 Unauthorized 响应。

我是否需要做一些特殊的事情才能在请求期间将此 cookie 发送回服务器?

更新 1: 也尝试使用 axios,使用 withCredentials: true。结果一样。

更新 2: 进一步检查,这似乎是因为浏览器出于某种原因没有保存 cookie,尽管事实上它是随响应一起到达的。也许它是一个单页应用程序的事实与此有关。我想这会带来一个问题:如何在 SPA 中使用会话 cookie?

【问题讨论】:

Vue.prototype.$http = axios.create( withCredentials: true ); 应该是您所需要的。这是您指定的方式吗? 我用 axios 做这个:this.axios.create(withCredentials: true).get("http://localhost:4000/api/account/").then(...) 如果您的服务器正在发送一个 set-cookie 标头,这应该由浏览器本身管理。唯一可能导致此问题的是您不在同一个域中。尝试为前端和后端设置具有虚拟域名的虚拟主机,看看它是否有效。 是的,这实际上是问题所在。我忘了把它作为答案发布。谢谢你提醒我。 【参考方案1】:

想通了。两个问题。首先,cookie 到达带有域localhost 的浏览器,但我实际上是在向我简单地映射到 localhost 的虚拟域发出请求。由于域不匹配,浏览器没有发送 cookie。

其次,这里是在Axios中使用withCredentials选项的正确方法:

axios.create(withCredentials: true).get(/* ... */)

由于某种原因,在请求本身中设置选项不起作用。

【讨论】:

以上是关于无法在 CORS 请求中发送凭据的主要内容,如果未能解决你的问题,请参考以下文章

在 CORS 中,是不是已预先发送带有凭据的 POST 请求?

如何使用凭据、HTTP 授权 (CORS) 使 XMLHttpRequest 跨域?

CORS AngularJS 不使用 POST 或 DELETE 发送 Cookie/凭据,但 GET OK

在 C# WebAPI 中,如何配置 CORS 以允许带有凭据和 json 内容的 POST 请求?

CORS:简单请求的目的是啥?

从 Blazor 发出 CORS 请求时如何包含凭据?