【发布时间】:2020-03-01 17:57:54
【问题描述】:
我已经为如何解决这个问题苦苦挣扎了几个小时,但我现在似乎无法解决这个问题。
正在构建一个简单的身份验证系统,其前端有Vue(使用vue-cli 创建),后端使用Laravel 5.8(api);在阅读this 文章后,测试使用 httponly cookie 进行身份验证和保护对某些路由的访问的想法。我使用tymondesigns/jwt-auth 进行身份验证,而不是文章中使用的laravel passport,并且还使用barryvdh/laravel-cors
包来添加CORS(跨域资源共享)标头支持。
后端
这是我在routes/api.php中的代码
Route::group(['prefix' => 'auth', 'namespace' => 'Auth'], function () {
Route::post('login', 'AuthController@login');
Route::group(['middleware' => ['auth.api'],], function () {
Route::get('me', 'AuthController@me');
Route::post('logout', 'AuthController@logout');
});
});
并且正在使用的中间件的代码在app/Http/Kernel.php中如下所示
'auth.api' => [
\App\Http\Middleware\AddAuthTokenHeader::class,
'throttle:60,1',
'bindings',
'auth:api',
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
],
这是我在app/Http/Controllers/Auth/AuthController.php中的代码
<?php
namespace App\Http\Controllers\Auth;
use App\Http\Requests\Auth\LoginRequest;
use App\Http\Controllers\Controller;
class AuthController extends Controller
{
/**
* Authenticate user via given credentials.
*
* @param \App\Http\Requests\Auth\LoginRequest $request
*
* @return \Illuminate\Http\JsonResponse
*/
public function login(LoginRequest $request)
{
$credentials = $request->all(['email', 'password']);
if (!$token = auth()->attempt($credentials)) {
return response()->json(['error' => 'Invalid credentials'], 401);
}
$cookie = $this->getCookie($token);
return response()->json([
'token' => $token,
'user' => auth()->user(),
])->withCookie($cookie);
}
/**
* Set cookie details and return cookie
*
* @param string $token JWT
*
* @return \Illuminate\Cookie\CookieJar|\Symfony\Component\HttpFoundation\Cookie
*/
private function getCookie($token)
{
return cookie(
env('AUTH_COOKIE_NAME'),
$token,
auth()->factory()->getTTL(),
null,
null,
env('APP_DEBUG') ? false : true,
true,
false,
'Strict'
);
}
public function logout()
{
// ...
}
public function me()
{
// ...
}
}
而自定义中间件auth.api中使用的中间件类(app/Http/Middleware/AddAuthTokenHeader.php)中handle方法的代码是
public function handle($request, Closure $next)
{
$cookie_name = env('AUTH_COOKIE_NAME');
if (!$request->bearerToken()) {
if ($request->hasCookie($cookie_name)) {
$token = $request->cookie($cookie_name);
$request->headers->add([
'Authorization' => 'Bearer ' . $token
]);
}
}
return $next($request);
}
正如您在我的AuthController 中看到的,一旦登录请求成功,json 响应就会与仅 http 的 cookie 一起发送。
注意:我正在使用php artisan serve 运行我的后端
前端
在我的vue-cli 生成的项目中运行npm run serve 后,我转到login 路由,该路由显示Login 由@/views/Login.vue 表示的组件。
这是我的Login.vue代码
<template>
<div>
<form @submit.prevent="submit" autocomplete="off">
<p>
<label for="email">Email: </label>
<input
type="email"
name="email"
id="email"
v-model.lazy="form.email"
required
autofocus
/>
</p>
<p>
<label for="password">Password: </label>
<input
type="password"
name="password"
id="password"
v-model.lazy="form.password"
required
/>
</p>
<button type="submit">Login</button>
</form>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'login',
data() {
return {
form: {
email: '',
password: '',
},
};
},
methods: {
async submit() {
const url = 'http://localhost:8000/api/auth/login';
const response = await axios.post(url, this.form, {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
});
console.log(response);
// this.$router.replace({ name: 'home' });
},
},
};
</script>
给定路由上的有效凭据(http:localhost:8080/login),cookie 将返回,如下面的响应标头所示
但由于某种原因,它没有设置在浏览器 cookie cookie 存储中,如下所示
注意:上面显示的 cookie 来自我在运行 php artisan serve 并在浏览器中打开 http:localhost:8000 后测试是否一切正常。
问题是,为什么 cookie 没有存储在浏览器 cookie 存储中。
我应该注意,当我使用 POSTMAN 调用相同的后端 api 路由时,一切正常(登录时设置 cookie,注销时清除)。
谢谢。
【问题讨论】:
-
我不熟悉 PHP,所以无法给出完整的答案,但我的第一个想法是您在请求中缺少
withCredentials。见developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/…。默认情况下,axios 不启用此功能,但您可以使用withCredentials: true启用它。我相信您还需要确保您的服务器没有使用*代替Access-Control-Allow-Origin,请参阅developer.mozilla.org/en-US/docs/Web/HTTP/Headers/… -
@skirtle 谢谢你的提示。让我试试你的建议,看看效果如何。
-
@skirtle 我尝试在我的 axios 标头中设置
withCredentials: true并将Access-Control-Allow-Origin限制为调用客户端,但它仍然无法正常工作。 -
withCredentials不是标题。请检查 axios 文档并确保将其放在正确的位置。 -
@digout 我知道你来自哪里;我认为您指的是此代码
return response()->json(['token' => $token, 'user' => auth()->user(),])->withCookie($cookie);。就我而言,我这样做了,所以我可以在我的vuex代码中使用它来进行用户身份验证,但事实证明,我不需要它。
标签: laravel vue.js cookies laravel-5.8