Laravel 中的单会话登录
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19510220/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Single Session Login in Laravel
提问by Joseph Szymborski
I'm trying to implement a user policy whereby only one user can login at a time. I'm trying to build this on top of Laravel's Auth driver.
我正在尝试实施一项用户策略,即一次只能登录一个用户。我正在尝试在 Laravel 的 Auth 驱动程序之上构建它。
I've thought of using the Session driver to store the sessions in the database and make the keys constant for each username. This is probably a terrible implementation because of session fixation.
我想过使用 Session 驱动程序将会话存储在数据库中,并使每个用户名的键保持不变。由于会话固定,这可能是一个糟糕的实现。
What would the implementation be like? What methods in the Auth driver should I be editing? Where would the common session key be stored?
实施会是什么样的?我应该编辑 Auth 驱动程序中的哪些方法?公共会话密钥将存储在哪里?
回答by Albin N
I recently did this.
我最近做了这个。
My solution was to set the session value when a user logs in. Then I had a small class checking if the session ID stored is the same as the current user who is logged in.
我的解决方案是在用户登录时设置会话值。然后我有一个小班级检查存储的会话 ID 是否与当前登录的用户相同。
If the user logs in from somewhere else the session ID in the DB will update and the "older" user will be logged out.
如果用户从其他地方登录,则数据库中的会话 ID 将更新,而“较老”的用户将被注销。
I didn't alter the Auth driver or anything, just put it on top when the user logs in. Below happens when login is successful:
我没有更改 Auth 驱动程序或任何东西,只是在用户登录时将其放在最上面。登录成功时会发生以下情况:
$user->last_session = session_id();
$user->save();
To check if the session is valid I used below
要检查会话是否有效,我在下面使用
if(session_id() != Auth::user()->last_session){
Auth::logout();
return true;
}
As you can see I added a column in the users table called last_session
如您所见,我在用户表中添加了一列名为 last_session
回答by Nicolay77
With Laravel 5.6 and superior:
使用 Laravel 5.6 及更高版本:
in LoginController add method
在 LoginController 添加方法
protected function authenticated()
{
\Auth::logoutOtherDevices(request('password'));
}
in Kernel
在内核中
remove comment from line
从行中删除注释
\Illuminate\Session\Middleware\AuthenticateSession::class,
That's it, the feature is now included in Laravel!
就是这样,该功能现在包含在 Laravel 中!
回答by Darkshifty
What i did in Laravel 5.7 is similar to Somwang's solution, however this will keep the newly logged in user active and logout the old user.
我在 Laravel 5.7 中所做的类似于 Somwang 的解决方案,但是这将使新登录的用户保持活动状态并注销旧用户。
Start with creating a middleware class:
从创建一个中间件类开始:
php artisan make:middleware CheckSingleSession
Add the following:
添加以下内容:
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Auth;
And write out the handle like this:
并像这样写出句柄:
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);
}
Make sure you also add it in your users migration file:
确保您还将它添加到您的用户迁移文件中:
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();
});
Then you should be able to add it to your routeMiddleware in the Kernel: project\app\Http\Kernel.php
然后你应该能够将它添加到你的内核中的路由中间件:project\app\Http\Kernel.php
'checksinglesession' => \App\Http\Middleware\CheckSingleSession::class,
(make sure you check the comma's)
(确保你检查逗号)
And we are done, now you can use it as route middleware. This way there is an active check on single sessions.
我们完成了,现在您可以将其用作路由中间件。这样可以对单个会话进行主动检查。
Route::group(['middleware' => ['auth' ,'checksinglesession'], 'prefix' => 'app'], function () {
Route::get('/dashboard', 'DashboardController@index')->name('dashboard.index');
});
回答by Somwang Souksavatd
my solution was extended from @Albin N for Laravel 5.* onward
我的解决方案是从@Albin N 为 Laravel 5.* 扩展而来的
add "last_session" column into table users
将“last_session”列添加到表用户中
make sure you allow this column is fill-able by adding "last_session" into $fillable on User model (User.php)
通过在 User 模型 (User.php) 上将“last_session”添加到 $fillable 中,确保允许此列可填充
protected $fillable = [
'name', 'email', 'password','last_session'
];
add authenticated() function into App/Http/Controllers/Auth/LoginController.php if you can't find it just make sure you have run php artisan make:auth
如果找不到,请在 App/Http/Controllers/Auth/LoginController.php 中添加 authenticated() 函数,请确保您已运行 php artisan make:auth
protected function authenticated()
{
// Update last_session after logged-in
User::find(Auth::id())->update(['last_session'=>Session::getId()]);
}
create new middleware class php artisan make:middleware SingleSession
创建新的中间件类 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');
}
}
finally call you SingleSession middleware class in kernel.php
最后在 kernel.php 中调用你的 SingleSession 中间件类
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\SingleSession::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
];
it will check every time before routes are being executed that's it! happy coding..!
它会在每次执行路线之前进行检查,就是这样!快乐编码...!
回答by Nazmus Shakib
This question is much earlier, but someone will be benefited through these easy steps. No need to make extra migration or something else.
这个问题要早得多,但有人会通过这些简单的步骤受益。无需进行额外的迁移或其他操作。
The first step is to comment out the:
第一步是注释掉:
\Illuminate\Session\Middleware\AuthenticateSession::class,
line from App\Http
Kernel.php
class.
\Illuminate\Session\Middleware\AuthenticateSession::class,
从App\Http
Kernel.php
班级线。
Secondly add this line in your login function just after login attempt successfully and before redirection:
\Auth::logoutOtherDevices(request('password'));
其次,在登录尝试成功之后和重定向之前,在您的登录函数中添加这一行:
\Auth::logoutOtherDevices(request('password'));
Thanks.
谢谢。