Laravel sanctum 获得 401 未授权

Posted

技术标签:

【中文标题】Laravel sanctum 获得 401 未授权【英文标题】:Getting 401 unauthorized for Laravel sanctum 【发布时间】:2020-08-08 19:18:18 【问题描述】:

我正在使用 Laravel Sanctum 和 Vuejs SPA。两者都位于同一个***域

Laravel backend : app.demo.localhost
Vue SPA : app-spa.demo.localhost

当使用 axios 从 VueJS SPA 调用并且成功设置 XSRF-TOKEN 时,登录和注销(端点)工作正常,但是当我调用其他 api 端点时,它给了我 401 未授权。

在 axios 中这是被设置的

axios.defaults.withCredentials = true;

我有以下配置

在 Laravel .env 中

SESSION_DRIVER=cookie
SESSION_DOMAIN=.demo.localhost
SANCTUM_STATEFUL_DOMAINS=app-spa.demo.localhost

在 Routes/Api.php

Route::middleware('auth:sanctum')->get('api/user', function (Request $request) 
   return $request->user();
);

在 cors.php 中

'paths' => ['api/*', 'sanctum/csrf-cookie', 'login', 'logout'],

'allowed_methods' => ['*'],

'allowed_origins' => ['*'],

'allowed_origins_patterns' => [],

'allowed_headers' => ['*'],

'exposed_headers' => [],

'max_age' => 0,

'supports_credentials' => true,

有人可以帮帮我吗?

【问题讨论】:

你上面没有显示,你在app/Http/Kernel.php中启用了sanctum中间件吗? laravel.com/docs/7.x/sanctum#spa-authentication 你解决了这个问题吗? 我在生产服务器上遇到了同样的问题,使用 react 和 axios。 O 开发服务器工作正常 有人解决这个问题吗?我正在使用自定义警卫成功登录。但是即使设置了 xsrf 令牌等,后续请求也会失败...... 面临同样的问题。如果有人找到它,请提供答案。 【参考方案1】:

如果您使用的是 php artisan serve,请将端口号添加到 SANCTUM_STATEFUL_DOMAINS。所以如果你的端口号是 8000:

SESSION_DRIVER=cookie
SESSION_DOMAIN=.demo.localhost
SANCTUM_STATEFUL_DOMAINS=app-spa.demo.localhost:8000

您的 SANCTUM_STATEFUL_DOMAINS 必须与您浏览器中的网址匹配。端口号不应在 SESSION_DOMAIN 上。

【讨论】:

我在 SESSION_DOMAIN 设置中添加了端口号,这使它返回 401 - 我删除了端口号,它立即工作 - 谢谢!【参考方案2】:

对于任何与本地主机打交道的人:

SESSION_DRIVER=cookie    
SESSION_DOMAIN=localhost    
SANCTUM_STATEFUL_DOMAINS=localhost:8080(port number you use)

【讨论】:

【参考方案3】:

我刚刚遇到了同样的问题。我按照官方文档配置了所有选项,但是无法获得授权。

那我用routes/web.php代替routes/api.php,这样可以很好的使用sanctum中间件。

现在问题似乎很明显了,Axios withCredentials 可能需要以正确的方式放置。

const http = axios.create(
    baseURL: API_URL,
    withCredentials: true
)

也许行不通。所以我加了withCredentials: truelike

http.get('/api/whoami', withCredentials: true)
  .then(res => 
                console.log(res.data)
            )

然后就可以了。

但是很奇怪的是现在正常了,不管我清除浏览器缓存、cookies还是Laravel的各种缓存,都没有以前的情况

【讨论】:

人...这是唯一对我有用的解决方案!谢谢。【参考方案4】:

以下是我在设置 Laravel sanctum 时遵循的 8 个步骤,检查你是否遗漏了什么

第一步 composer require laravel/sanctum

第二步 php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider

Step3 php artisan migrate(如果您正在使用水疗,可以忽略此)

Step4 从 app/http/kernel.php \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, 取消注释此行

Step5在config/cors.php中更新'supports_credentials' => true,

Step6 在 .env 文件中更新 SESSION_DRIVER=cookie 并添加 SESSION_DOMAIN=localhost 的新行(即使您使用像 8080 这样的任何端口,只需在 session_domain 中提及 localhost

Step7 在 config/sanctum.php 中添加您的客户端域以及端口(如果是本地),如下所示,在我的情况下,对于 vue CLI,它通常是 localhost:8080 &对于 nuxt 它的 @987654329 @ ,代码如下

    'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
        '%s%s',
        'localhost,localhost:8000,localhost:8080,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
        env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
    ))),

大多数情况下,如果您的状态(步骤 7)设置不正确,您将获得 401 未授权,或者它会尝试将您重定向到主页以及 cors 策略错误

Step8在解决sanctum/csrf-cookie 承诺之前不要忘记await

    async login() 
      await axios.get("http://localhost:8000/sanctum/csrf-cookie");

      await axios.post("http://localhost:8000/login", 
        email: "kunal@gmail.com",
        password: "password",
      );

      let response = await axios.get("http://localhost:8000/api/user");
      console.log(response.data);
    ,

【讨论】:

【参考方案5】:

我的问题是....(没有仔细阅读)

如果您的 SPA 需要使用私有/在线广播频道进行身份验证,您应该将 Broadcast::routes 方法调用放在 您的 routes/api.php 文件e中:

【讨论】:

【参考方案6】:

您好,我找到了解决方案。

我的 SPA 是在 3000 端口上运行的 Vue v3。 我的后端也在 80 端口上工作。 (laravel 8.1)

像这样在 config/sanctum.php 中创建有状态域

 'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
    '%s%s',
    'localhost:3000',
    env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
))),

仅在其上添加一个正确的域,这对我来说很神奇。我之前写过所有可能的端口变体,这让我抓狂并且花费了几天几夜。

【讨论】:

【参考方案7】:

我的问题是我在错误的地方设置了域。 我以为是一个域数组,在config/sanctum.php,但不是,需要放在字符串中:

好的:

    'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
        '%s%s',
'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1,myownlocaldomain.test,myownlocaldomain.test:8080', <-------- OK
        env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
    ))),

不好:

    'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
        '%s%s',
        'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
        env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : '',
        'myownlocaldomain.test', <----- BAD
        'myownlocaldomain.test:8080', <---- BAD
    ))),

我希望我能把几天的工作留给别人...

【讨论】:

以上是关于Laravel sanctum 获得 401 未授权的主要内容,如果未能解决你的问题,请参考以下文章

使用 nuxtjs 登录 laravel sanctum 后出现 401(未验证)错误

如何使用 Laravel Sanctum 和 React 修复 401 Unauthorized 错误?

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

Laravel Sanctum 和使用 Pusher.js 进行广播(401、419 错误)

使用 laravel Sanctum 和 api 令牌身份验证获取用户时出现 401(未经授权)[重复]

自定义 laravel sanctum 未授权响应