19

我正在尝试实施一项用户策略,即一次只能有一个用户登录。我正在尝试在 Laravel 的 Auth 驱动程序之上构建它。

我曾考虑使用 Session 驱动程序将会话存储在数据库中,并使每个用户名的键值保持不变。由于会话固定,这可能是一个糟糕的实现。

实施会是什么样子?我应该编辑 Auth 驱动程序中的哪些方法?通用会话密钥将存储在哪里?

4

6 回答 6

25

我最近做了这个。

我的解决方案是在用户登录时设置会话值。然后我有一个小班检查存储的会话 ID 是否与当前登录的用户相同。

如果用户从其他地方登录,数据库中的会话 ID 将更新,“老”用户将被注销。

我没有更改 Auth 驱动程序或任何东西,只是在用户登录时将其放在顶部。登录成功时会发生以下情况:

$user->last_session = session_id();
$user->save();

要检查会话是否有效,我在下面使用

if(session_id() != Auth::user()->last_session){
   Auth::logout();
   return true;
}

如您所见,我在 users 表中添加了一个名为last_session

于 2013-10-22T06:22:46.600 回答
14

使用 Laravel 5.6 及更高版本:

在 LoginController 添加方法

protected function authenticated()
{
    \Auth::logoutOtherDevices(request('password'));
}

在内核中

从行中删除评论

\Illuminate\Session\Middleware\AuthenticateSession::class,

就是这样,该功能现在包含在 Laravel 中!

于 2018-05-10T17:18:18.767 回答
11

我在 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');
});
于 2019-02-20T07:59:42.563 回答
3

我的解决方案是从@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',
    ],
];

它会在每次执行路线之前检查就是这样!快乐编码..!

于 2018-03-29T07:10:52.083 回答
1

这个问题要早得多,但有人会通过这些简单的步骤受益。无需进行额外的迁移或其他操作。

第一步是注释掉:

\Illuminate\Session\Middleware\AuthenticateSession::class,App\Http Kernel.php课堂线。

其次,在登录尝试成功之后和重定向之前在您的登录功能中添加这一行: \Auth::logoutOtherDevices(request('password'));

谢谢。

于 2019-04-14T17:58:14.430 回答
0

这是您如何完成此操作的方法。首先,您需要取消注释 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/

演示 https://xpredo.com

于 2020-11-02T00:58:33.337 回答