我已经在如何解决这个问题上苦苦挣扎了几个小时,而我似乎暂时无法解决它。
正在使用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一起发送。
注意:我正在使用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存储中设置它,如下所示。
注意:上面显示的cookie是由我测试的,它测试在运行php artisan serve
并在浏览器中打开http:localhost:8000
后一切是否正常运行。
问题是,为什么cookie不存储在浏览器cookie存储中?
我应该注意,当我使用POSTMAN
调用相同的后端api路由时,一切正常(在登录时设置cookie,并在注销时清除cookie)。
谢谢。
答案 0 :(得分:0)
感谢@skirtle帮助我解决了这个问题;您的帮助非常宝贵。
这是我为使其工作而采取的步骤。
我运行命令php artisan vendor:publish --provider="Barryvdh\Cors\ServiceProvider"
,该命令在cors.php
目录下创建文件config
。
然后我将'supportsCredentials' => false,
中的这一行config/cors.php
更改为'supportsCredentials' => true,
,并保持所有其他内容不变,然后运行以下命令以确保已捕获新更改。 / p>
php artisan config:clear
php artisan cache:clear
php artisan serve
我所要做的就是将submit
中的Login.vue
方法更改为此
async submit() {
const url = 'http://localhost:8000/api/auth/login';
const response = await axios.post(url, this.form, {
withCredentials: true,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
});
console.log(response.data);
// this.$router.replace({ name: 'home' });
},
现在如下所示设置cookie
再次感谢和感谢@skirtle的提示。