我正在尝试实施一个用户策略,一次只能有一个用户登录。我正试图在Laravel的Auth驱动程序之上构建它。
我曾想过使用Session驱动程序将会话存储在数据库中,并使每个用户名的密钥保持不变。由于会话固定,这可能是一个糟糕的实现。
实施是什么样的?我应该编辑Auth驱动程序中的哪些方法?公共会话密钥存储在哪里?
答案 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/