我已经在这个问题上苦苦挣扎了几个小时,以解决这个问题,我似乎暂时无法解决。
正在构建具有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() { // ... } }
并且自定义中间件
app/Http/Middleware/AddAuthTokenHeader.php
中使用的中间件类(auth.api
)中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一起发送。
NOTE
:我正在使用php artisan serve
运行我的后端在我的npm run serve
生成的项目中运行vue-cli
之后,转到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存储中进行设置,如下所示
NOTE
:上面显示的cookie是我测试的,它运行php artisan serve
并在浏览器中打开http:localhost:8000
后,是否一切运行正常。问题是,为什么cookie不存储在浏览器cookie存储中。
[我应该注意,当我使用POSTMAN
调用相同的后端api路由时,一切正常(在登录时设置cookie,并在注销时清除cookie)。
谢谢。
我已经在这个问题上苦苦挣扎了几个小时,以解决这个问题,但我似乎暂时无法解决。我正在使用Vue前端构建一个简单的身份验证系统...
感谢@skirtle帮我解决了这个问题;您的帮助非常宝贵。