为什么即使调用了正确的先决中间件,也无法在全局 Laravel 中间件中访问 `$request->user()` ?

问题描述 投票:0回答:1

这更像是一个学术问题,而不是现实世界的问题,尽管当我在中间件配置错误的遗留 5.2 项目中遇到它时,它让我感到困惑,并且它的行为在 Laravel 11 中没有改变。虽然也有人提出了类似的问题在互联网上,结果总是有人忘记在失败的中间件之前移动适当的中间件。这是不一样的。

一些上下文:开箱即用,Laravel 附带全局、“web”和“api”中间件组。 一旦用户通过基于 cookie 的常规会话进行身份验证,

\Illuminate\Cookie\Middleware\EncryptCookies::class
\Illuminate\Session\Middleware\StartSession::class
中间件是加载该用户以通过
auth()->user()
$request->user()
访问所需的唯一内容。这些中间件作为默认“web”组的一部分包含在内。

中间件按照列出的顺序依次执行。全局中间件总是首先执行。然而,将上述“Web”中间件提升到全局仍然有效,但当从之后调用的全局中间件引用时,会导致

$request->user()
变为
null
。换句话说:

// app/Http/Middleware/Test.php

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;

class Test
{
    public function handle(Request $request, Closure $next)
    {
        dd($request->user()); // `null` when global and `App\Models\User` when not
        dd(auth()->user()); // This always works
    }
}

这是其余的代码:

// bootstrap/app.php

<?php

use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Middleware;

return Application::configure(basePath: dirname(__DIR__))
    ->withRouting(
        web: __DIR__.'/../routes/web.php',
    )
    ->withMiddleware(function (Middleware $middleware) {

        // This doesn't work...

        $middleware->use([
            \Illuminate\Cookie\Middleware\EncryptCookies::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \App\Http\Middleware\Test::class,
        ]);

        $middleware->group('web', []); // Clear out default web middleware


        // But this works...

        $middleware->use([
            \Illuminate\Cookie\Middleware\EncryptCookies::class,
            \Illuminate\Session\Middleware\StartSession::class,
        ]);

        $middleware->group('web', [
            \App\Http\Middleware\Test::class,
        ]);


        // And this also works...

        $middleware->use([]); // Clear out default global middleware

        $middleware->group('web', [
            \Illuminate\Cookie\Middleware\EncryptCookies::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \App\Http\Middleware\Test::class,
        ]);

    })
    ->create();
// routes/web.php

<?php

use Illuminate\Support\Facades\Route;

Route::get('', fn() => 'It works!');

我对 Laravel 源代码进行了一些挖掘,但很快就陷入了困境。值得注意的是,

$request->user()
始终由
StartSession
这一行的时间设置,无论它是否是全局的。

我很满意这种行为是一致的并且似乎是有意为之,但我希望有更多知识的人可以解释为什么会这样。

php laravel
1个回答
0
投票

据我所知,要使用

$request->user()
session middleware必须在此之前执行过。

auth()->user()
独立于请求的初始化状态工作,因为它直接与身份验证服务交互。

$request->user()
依赖于request对象,需要会话中间件先初始化session(
StartSession
)

\Illuminate\Session\Middleware\StartSession::class,

© www.soinside.com 2019 - 2024. All rights reserved.