Laravel 8 中的自定义 DatabaseSessionHandler

Custom DatabaseSessionHandler in Laravel 8

我正在尝试自定义 DatabaseSessionHandler 但它没有按预期工作。 这个想法是使 table sessions 多态以允许来自多个模型的 session 。 (老实说,我什至不确定这是否可能)
但即使在将 table 更改为多态之前,我也在尝试添加自定义驱动程序以操纵 sessions.
问题似乎是我的 DatabaseSessionHandler 在我尝试登录时未正确调用。

config/auth.php

'guards' => [
    'web'    => [
        'driver'   => 'custom-session',
        'provider' => 'users',
    ],
    'screen' => [
        'driver'   => 'custom-session',
        'provider' => 'screens',
    ],
],
'providers' => [
    'users'   => [
        'driver' => 'eloquent',
        'model'  => Domain\User\Models\User::class,
    ],
    'screens' => [
        'driver' => 'eloquent',
        'model'  => Domain\Screen\Models\Screen::class,
    ],
]

AuthServiceProvider.php

public function boot()
{
   //This is how the session is normally registered: https://github.com/laravel/framework/blob/8.x/src/Illuminate/Session/SessionManager.php#L83
    Session::resolved(function ($session) {
        $session->extend('screen-session', function ($app) {
            $table = $app['config']['session.table'];
            $lifetime = $app['config']['session.lifetime'];
            $connection = $app['db']->connection($app['config']['session.connection']);
            return new \Support\Session\DatabaseSessionHandler($connection, $table, $lifetime, $app);
        });
    });

    // This is how the driver "session" is normally registered: https://github.com/laravel/framework/blob/8.x/src/Illuminate/Auth/AuthManager.php#L121
    Auth::resolved(function ($auth) {
        $auth->extend('custom-session', function ($app, $name, array $config) {
            $provider = Auth::createUserProvider($config['provider']);

            $guard = new SessionGuard($name, $provider, $app->session->driver('screen-session'));

            if (method_exists($guard, 'setCookieJar')) {
                $guard->setCookieJar($this->app['cookie']);
            }

            if (method_exists($guard, 'setDispatcher')) {
                $guard->setDispatcher($this->app['events']);
            }

            if (method_exists($guard, 'setRequest')) {
                $guard->setRequest($this->app->refresh('request', $guard, 'setRequest'));
            }
            return $guard;
        });
    });

}

DatabaseSessionHandler.php
目前这是 copy/pastsession 使用的现有的,但命名空间除外。 https://github.com/laravel/framework/blob/8.x/src/Illuminate/Session/DatabaseSessionHandler.php


我没有任何错误信息。

当我尝试登录时 (auth()->guard('web')->login($user))

另一种情况;

从守卫中移除 screenproviders 以仅保留 webusers,不会改变任何东西。

终于解决了。一如既往,这是一个简单的错误。

我在.env文件中添加更改

SESSION_DRIVER=screen-session

现在一切正常。


现在,也回答我的另一个问题

The idea is to make the table sessions polymorphic to allow the session from multiple models. (To be honest, I'm not even sure it's possible)

根据我的快速测试,它看起来是可行的。这是我所做的;

create_sessions_table.php

Schema::create('sessions', function (Blueprint $table) {
    $table->string('id')->primary();
    $table->nullableMorphs('authenticable');
    $table->string('ip_address', 45)->nullable();
    $table->text('user_agent')->nullable();
    $table->text('payload');
    $table->integer('last_activity')->index();
});

DatabaseSessionHandler.php

use Illuminate\Contracts\Auth\Guard;
use Illuminate\Session\DatabaseSessionHandler as BaseDatabaseSessionHandler;

class DatabaseSessionHandler extends BaseDatabaseSessionHandler
{

    /**
     * Get the currently authenticated user's type.
     *
     * @return mixed
     */
    protected function userType()
    {
        $user = $this->container->make(Guard::class)->user();
        return optional($user)->getMorphClass();
    }

    /**
     * Add the user information to the session payload.
     *
     * @param array $payload
     * @return $this
     */
    protected function addUserInformation(&$payload)
    {
        if ($this->container->bound(Guard::class)) {
            $payload['authenticable_id'] = $this->userId();
            $payload['authenticable_type'] = $this->userType();
        }

        return $this;
    }

}

注意:如果您使用的是 Laravel jetstream,您可能需要自定义 LogoutOtherBrowserSessionsForm livewire/inertiajs 组件,因为该组件基于database 会话并查找 user_id