我正在尝试实施一项用户策略,即一次只能有一个用户登录。我正在尝试在 Laravel 的 Auth 驱动程序之上构建它。
我曾考虑使用 Session 驱动程序将会话存储在数据库中,并使每个用户名的键值保持不变。由于会话固定,这可能是一个糟糕的实现。
实施会是什么样子?我应该编辑 Auth 驱动程序中的哪些方法?通用会话密钥将存储在哪里?
我正在尝试实施一项用户策略,即一次只能有一个用户登录。我正在尝试在 Laravel 的 Auth 驱动程序之上构建它。
我曾考虑使用 Session 驱动程序将会话存储在数据库中,并使每个用户名的键值保持不变。由于会话固定,这可能是一个糟糕的实现。
实施会是什么样子?我应该编辑 Auth 驱动程序中的哪些方法?通用会话密钥将存储在哪里?
我最近做了这个。
我的解决方案是在用户登录时设置会话值。然后我有一个小班检查存储的会话 ID 是否与当前登录的用户相同。
如果用户从其他地方登录,数据库中的会话 ID 将更新,“老”用户将被注销。
我没有更改 Auth 驱动程序或任何东西,只是在用户登录时将其放在顶部。登录成功时会发生以下情况:
$user->last_session = session_id();
$user->save();
要检查会话是否有效,我在下面使用
if(session_id() != Auth::user()->last_session){
Auth::logout();
return true;
}
如您所见,我在 users 表中添加了一个名为last_session
使用 Laravel 5.6 及更高版本:
在 LoginController 添加方法
protected function authenticated()
{
\Auth::logoutOtherDevices(request('password'));
}
在内核中
从行中删除评论
\Illuminate\Session\Middleware\AuthenticateSession::class,
就是这样,该功能现在包含在 Laravel 中!
我在 Laravel 5.7 中所做的与 Somwang 的解决方案类似,但是这将使新登录的用户保持活动状态并注销旧用户。
从创建中间件类开始:
php artisan make:middleware CheckSingleSession
添加以下内容:
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Auth;
并像这样写出句柄:
public function handle($request, Closure $next)
{
$previous_session = Auth::User()->session_id;
if ($previous_session !== Session::getId()) {
Session::getHandler()->destroy($previous_session);
$request->session()->regenerate();
Auth::user()->session_id = Session::getId();
Auth::user()->save();
}
return $next($request);
}
确保您还将它添加到您的用户迁移文件中:
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('firstName');
$table->string('lastName');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->string('session_id')->nullable();
$table->rememberToken();
$table->timestamps();
});
然后你应该可以将它添加到内核中的 routeMiddleware 中:project\app\Http\Kernel.php
'checksinglesession' => \App\Http\Middleware\CheckSingleSession::class,
(确保检查逗号)
我们完成了,现在您可以将它用作路由中间件。这样就可以对单个会话进行主动检查。
Route::group(['middleware' => ['auth' ,'checksinglesession'], 'prefix' => 'app'], function () {
Route::get('/dashboard', 'DashboardController@index')->name('dashboard.index');
});
我的解决方案是从@Albin N for Laravel 5.* 开始扩展的
将“last_session”列添加到表用户中
通过在用户模型 (User.php) 上的 $fillable 中添加“last_session”来确保允许此列是可填充的
protected $fillable = [
'name', 'email', 'password','last_session'
];
如果找不到,请将 authenticated() 函数添加到 App/Http/Controllers/Auth/LoginController.php 中,只需确保已运行php artisan make:auth
protected function authenticated()
{
// Update last_session after logged-in
User::find(Auth::id())->update(['last_session'=>Session::getId()]);
}
创建新的中间件类php artisan make:middleware SingleSession
if(Auth::check())
{
// If current session id is not same with last_session column
if(Auth::user()->last_session != Session::getId())
{
// do logout
Auth::logout();
// Redirecto login page
return Redirect::to('login');
}
}
最后在 kernel.php 中调用你 SingleSession 中间件类
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\SingleSession::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];
它会在每次执行路线之前检查就是这样!快乐编码..!
这个问题要早得多,但有人会通过这些简单的步骤受益。无需进行额外的迁移或其他操作。
第一步是注释掉:
\Illuminate\Session\Middleware\AuthenticateSession::class,
从App\Http
Kernel.php
课堂线。
其次,在登录尝试成功之后和重定向之前在您的登录功能中添加这一行:
\Auth::logoutOtherDevices(request('password'));
谢谢。
这是您如何完成此操作的方法。首先,您需要取消注释 app/Http/Kernel.php 文件中 $middlewareGroups 属性中的 \Illuminate\Session\Middleware\AuthenticateSession::class 行,因为这是在 Laravel 中管理用户会话的中间件。
2-在登录尝试成功之后和重定向之前在您的登录功能中添加此行:\Auth::logoutOtherDevices(request('password'));
use Illuminate\Support\Facades\Auth;
Auth::logoutOtherDevices($password);
if(Auth::guard('student')->attempt([],$request->rememberme))
{
Auth::guard('student')->logoutOtherDevices(request('password'));
return redirect()->intended('/'); //route('homepage');
}
https://www.amitmerchant.com/logout-from-everywhere-except-current-device-laravel/