【发布时间】:2020-02-23 14:29:45
【问题描述】:
我有两个应用程序,一个是用 Laravel 编写的服务器端应用程序,另一个是用 VueJS 编写的客户端应用程序。 vue 应用使用 laravel 应用提供的 api。
身份验证流程:
用户尝试登录,服务器向客户端发送两个令牌,a)access_token 和 b)成功登录后的refresh_token。服务器还会以httpOnly cookie 的形式向客户端发送刷新令牌,这样当访问令牌过期时,可以使用来自 cookie 的刷新令牌进行刷新。
问题:
当用户登录时,服务器会在响应中发送以下Set-Cookie 标头:
设置 Cookie: refresh_token=令牌值; 过期=星期一,2019 年 11 月 4 日 09:13:28 GMT;最大年龄=604800; 路径=/v1/刷新;域=http://app.test;仅限http;同站点=无
这意味着,只要有对 /v1/refresh 端点的请求,我希望将 cookie 发送到服务器。但是,请求中不存在 cookie。 (我在控制器中记录了$request->cookie('refresh_token'),但它记录了null)。
整个令牌刷新机制在 vuex 动作中处理:
export function refreshToken({commit}, payload) {
return new Promise((resolve, reject) => {
// axios.defaults.withCredentials = true;
// here, payload() function just converts the url to:
// "http://app.test/v1/refresh"
axios.post(payload('/refresh'), {}, {
withCredentials: true, transformRequest: [(data, headers) => {
delete headers.common.Authorization;
return data;
}]
}).then(response => {
let token = response.data.access_token;
localStorage.setItem('token', token);
commit('refreshSuccess', token);
resolve(token);
}).catch(err => reject(err));
});
}
如您所见,我已将 withCredentials 配置设置为 true。我还从服务器发送Access-Control-Allow-Credentials: true。这是我的 cors 中间件:
public function handle($request, Closure $next)
{
$whiteList = ['http://localhost:8080'];
if (isset($request->server()['HTTP_ORIGIN'])) {
$origin = $request->server()['HTTP_ORIGIN'];
if (in_array($origin, $whiteList)) {
header('Access-Control-Allow-Origin: ' . $request->server()['HTTP_ORIGIN']);
header('Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, Authorization');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Expose-Headers: Content-Disposition');
}
}
return $next($request);
}
我不知道我做错了什么。我的 PHP 版本是:7.3.5。这里是/v1/refresh端点的请求头:
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9,bn;q=0.8
Connection: keep-alive
Content-Length: 15
Content-Type: application/x-www-form-urlencoded
Host: app.test
Origin: http://localhost:8080
Referer: http://localhost:8080/products
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36
...以及响应标头:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: Origin, Content-Type, Authorization
Access-Control-Allow-Methods: GET, POST, PATCH, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin: http://localhost:8080
Access-Control-Expose-Headers: Content-Disposition
Cache-Control: no-cache, private
Connection: keep-alive
Content-Type: application/json
Date: Mon, 28 Oct 2019 09:40:31 GMT
Server: nginx/1.15.5
Transfer-Encoding: chunked
X-Powered-By: PHP/7.3.5
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
我不知道浏览器的cookie存储机制的内部工作原理,我也不知道是否可以在文件系统中找到httpOnly cookie,但绝望地想知道浏览器是否确实保存了cookie,我用谷歌搜索,发现 cookie 存储在~/Library/Application Support/Google/Chrome/Default/Cookies 文件中,这是一个 SQLite 文件。我打开了那个文件并搜索了我的 cookie ????,但它也不存在(也许 httpOnly cookie 存储在其他地方?)。
现在,我的问题是,如何从客户端应用中检索 cookie?
【问题讨论】:
-
您的主机到底是什么?是
localhost:8080还是app.test? -
感谢您的回复。
localhost:8080是提供我的 vue 应用程序的地方。app.test是我的 laravel 应用程序的来源。它们是两个不同的应用程序/域/来源。这是一个非常典型的 SPA 设置,它与 laravel 应用程序完全隔离。 -
那么,vue app 和 api 有不同的主机,对吧?当然它不会起作用,因为你的 laravel 将 cookie 设置为
app.test,而不是localhost:8080。看一下域名path=/v1/refresh; domain=http://app.test; httponly; samesite=none。
标签: laravel vue.js cookies axios