带有 Vuejs 的 Laravel 7.x Sanctum (SPA) 总是返回 401 Unauthorized

Posted

技术标签:

【中文标题】带有 Vuejs 的 Laravel 7.x Sanctum (SPA) 总是返回 401 Unauthorized【英文标题】:Laravel 7.x Sanctum (SPA) with Vuejs always returns 401 Unauthorized 【发布时间】:2020-10-02 21:24:58 【问题描述】:

因此,即使通读并尝试互联网上任何可能的解决方案,我也无法弄清楚问题所在。我将 Laravel 7.xVue js 一起使用,并在 Sanctum SPA 身份验证方面苦苦挣扎。

Login 请求工作正常,它使用 web.php 中定义的 Auth::routes()

但是,auth:sanctum 中间件api.php 中定义的 API 发出的任何请求都会返回 401。例如,调用 fetch用户对象失败,状态为 401:

这是请求标头:

这是 web.php

这是 api.php

这是 sanctum.php

中的 stateful 对象

'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost,127.0.0.1,127.0.0.1:8000')),

在 vue.js 方面,我已将 withCredentials 标志设置为 true:

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

window.axios.defaults.withCredentials = true;

cors.php 中,suports_credentials 标志也设置为 true

还有,这是我的 Kernel.php

/**
     * The application's route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            // \Illuminate\Session\Middleware\AuthenticateSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],

        'api' => [
            EnsureFrontendRequestsAreStateful::class,
            'throttle:60,1',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
    ];

【问题讨论】:

EnsureFrontendRequestsAreStateful::class 是什么,为什么它在内核文件命名空间中?既然你想要有状态的会话,为什么不使用 web 组而不是 api 一个呢?如果 URL 中的前缀 /api 恰到好处,即使使用 web 组,您也可以更改它。 我正在关注 Laravel 文档以进行 Sanctum SPA 身份验证。见laravel.com/docs/7.x/sanctum#spa-configuration 您找到解决方案了吗?我按照 laravel.com/docs/7.x 中的说明进行操作,但他们给出的说明有限。 【参考方案1】:

我遇到了同样的问题,但我找不到任何答案,但在排除故障后我得到了它。

您的问题是您通过 localhost 端口 8000 访问它,但在您的 sanctum 配置下的有状态参数中没有 localhost:8000(甚至 localhost 指向 127.0.0.1)。该配置使用$_SERVER['SERVER_NAME'],因此它实际上会在访问时查找确切的内容。

下面的简单修复:

'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', implode(',', [
    'localhost',
    'localhost:8000',
]))),

【讨论】:

非常感谢,伊卡罗。这让我整天摸不着头脑。这么愚蠢的事情,但我认为它也应该在官方文档的某个地方提到。 Icaro 有答案,但是,您应该将其添加到您的 .env 文件中作为 SANCTUM_STATEFUL_DOMAINS="localhost:8000" 而不是 sanctum.php 文件 @aseladaskon 你能详细说明你使用的是哪些软件包版本、urls/ips? 你好Ícaro R. Scherma,我决定跳过这个认证包。我正在使用 spatie 包。【参考方案2】:

我没有使用 Sanctum,而是使用 Vuejs Laravel 和 Axios,我注意到您需要在所有受 axios 保护的 URL 中添加标头 Authorization

承载 YOURTOKENKEY

在我使用的 ap.js 上

import jwtToken from './helpers/jwt-token'

    axios.interceptors.request.use(config => 
        config.headers['X-CSRF-TOKEN'] = window.Laravel.csrfToken
        config.headers['X-Requested-With'] = 'XMLHttpRequest'

        if (jwtToken.getToken()) 
            config.headers['Authorization'] = 'Bearer ' + jwtToken.getToken()
        

        return config;
    , error => 
        return Promise.reject(error);
    );

还有我的 JWTTOKEN js 文件

export default 
    setToken(token) 
        window.localStorage.setItem('jwt_token', token);
    ,
    getToken() 
        return window.localStorage.getItem('jwt_token');
    ,

所以 axios 的所有请求都使用 Bearer + token 发送 Authorization 标头

希望对你有帮助

【讨论】:

这是一种有状态的会话方式,会自动发送 X-CRF-TOKEN。见laravel.com/docs/7.x/sanctum#spa-configuration

以上是关于带有 Vuejs 的 Laravel 7.x Sanctum (SPA) 总是返回 401 Unauthorized的主要内容,如果未能解决你的问题,请参考以下文章

带有laravel混合的vuejs的大app.js文件大小(13 MB)

Laravel、惯性和 vuejs

形成 laravel 和 vueJS

Laravel & VueJS 变量定义

将 VueJS 添加到 Laravel 但继续使用 Laravel 的路由器等

Laravel 5.4 事件广播不适用于 vuejs