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/past 的 session
使用的现有的,但命名空间除外。 https://github.com/laravel/framework/blob/8.x/src/Illuminate/Session/DatabaseSessionHandler.php
我没有任何错误信息。
当我尝试登录时 (auth()->guard('web')->login($user)
)
- 它验证登录
- 我知道它用我的
DatabaseSessionHandler
来破坏电流
session 在 table.
- session ID 已重新生成,我未 登录
另一种情况;
- 我尝试使用“记住我”登录。
- 它验证登录
- 不知何故,数据库中的 session 已更新为当前
user_id
,但我的 DatabaseSessionHandler
似乎没有被使用
- 我已登录
从守卫中移除 screen
和 providers
以仅保留 web
和 users
,不会改变任何东西。
终于解决了。一如既往,这是一个简单的错误。
我在.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
列
我正在尝试自定义 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/past 的 session
使用的现有的,但命名空间除外。 https://github.com/laravel/framework/blob/8.x/src/Illuminate/Session/DatabaseSessionHandler.php
我没有任何错误信息。
当我尝试登录时 (auth()->guard('web')->login($user)
)
- 它验证登录
- 我知道它用我的
DatabaseSessionHandler
来破坏电流 session 在 table. - session ID 已重新生成,我未 登录
另一种情况;
- 我尝试使用“记住我”登录。
- 它验证登录
- 不知何故,数据库中的 session 已更新为当前
user_id
,但我的DatabaseSessionHandler
似乎没有被使用 - 我已登录
从守卫中移除 screen
和 providers
以仅保留 web
和 users
,不会改变任何东西。
终于解决了。一如既往,这是一个简单的错误。
我在.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
列