无法在 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