未设置/存储 Httponly cookie (Laravel / Vue)

kel*_*dem 3 cookies laravel vue.js laravel-5.8

关于如何解决这个问题,我已经为此苦苦挣扎了几个小时,但我现在似乎无法解决它。

正在构建一个简单的身份验证系统,Vue前端(使用创建vue-cli)和Laravel 5.8后端(api);看完后,测试出来使用的HttpOnly的cookie进行身份验证和访问某些航线的保护理念文章。我使用tymondesigns/jwt-auth进行身份验证而不是文章中使用的laravel 护照,并且还使用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');
    });
});
Run Code Online (Sandbox Code Playgroud)

我使用的中间件的代码如下 app/Http/Kernel.php

'auth.api' => [
    \App\Http\Middleware\AddAuthTokenHeader::class,
    'throttle:60,1',
    'bindings',
    'auth:api',
    \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
],
Run Code Online (Sandbox Code Playgroud)

这是我的代码 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()
    {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

app/Http/Middleware/AddAuthTokenHeader.php自定义中间件中使用的中间件类( )中的handle方法的代码auth.api

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);
}
Run Code Online (Sandbox Code Playgroud)

正如您在我AuthController的登录请求成功后看到的那样,json 响应与 http-only 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>
Run Code Online (Sandbox Code Playgroud)

给定 route( http:localhost:8080/login)上的有效凭据,cookie 将被返回,如下面的响应头所示

在此处输入图片说明

但由于某种原因,它没有被设置在浏览器 cookie cookie 存储中,如下所示

在此处输入图片说明

注意:上面显示的 cookie 来自我测试在浏览器中运行php artisan serve和打开后是否一切正常http:localhost:8000

问题是,为什么 cookie 没有存储在浏览器 cookie 存储中。

我应该注意,当我使用 调用相同的后端 api 路由时POSTMAN,一切正常(cookie 在登录时设置并在注销时清除)。

谢谢你。

kel*_*dem 6

感谢@skirtle 帮助我解决了这个问题;你的帮助是无价的。

以下是我为使其工作而采取的步骤。

后端

我运行在目录下php artisan vendor:publish --provider="Barryvdh\Cors\ServiceProvider"创建文件的命令。cors.phpconfig

然后,我改变了这一行'supportsCredentials' => false,config/cors.php'supportsCredentials' => true,,我就走了一切同之后我运行下面的命令,以确保公正的新变化被抓获。

php artisan config:clear
php artisan cache:clear

php artisan serve
Run Code Online (Sandbox Code Playgroud)

前端

我所要做的就是将我的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' });
},
Run Code Online (Sandbox Code Playgroud)

现在cookie被设置为如下所示

在此处输入图片说明

再次感谢@skirtle 的提示。