Laravel中的单个会话登录

时间:2013-10-22 06:10:37

标签: php security authentication laravel

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

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

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

5 个答案:

答案 0 :(得分:15)

我最近这样做了。

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

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

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

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

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

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

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

的列

答案 1 :(得分:2)

我的解决方案从@Albin N扩展到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',
    ],
];

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

答案 2 :(得分:1)

我在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');
});

答案 3 :(得分:0)

这个问题要早得多,但是通过这些简单的步骤,将使某人受益。无需进行其他迁移。

第一步是将以下内容注释掉:

\Illuminate\Session\Middleware\AuthenticateSession::class, App\Http Kernel.php类的一行。

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

谢谢。

答案 4 :(得分: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