Laravel 5.2 - Как выйти из системы пользователя со всех его устройств
Когда пользователь выходит из системы с пертикулярного устройства, я хочу выйти из всех устройств, на которых он входил до сих пор. Как я это делаю в Laravel.
Я использовал Redis для сохранения идентификатора пользователя в сеансе, установив "predis/predis": "~1.0"
А вот мой контроллер для входа и выхода из системы:
public function postSignIn(Request $request)
{
if (Auth::attempt(['email' => $request['email'], 'password' =>$request['password'] ]) ) {
$redis = \Redis::connection();
$userId=Session::getId();
$redis->sadd('users:sessions:'.$userId,Session::getId());
return redirect()->route('main');
}
return redirect()->back();
}
public function getLogout()
{
$redis = Redis::connection();
$userId=Session::getId();
$userSessions = $redis->smembers('user:sessions:' . $userId);
$currentSession = Session::getId();
foreach ($userSessions as $sessionId) {
if ($currentSession == $sessionId) {
continue;
}
$redis->srem('user:sessions:' . $userId, $sessionId);
$redis->del('laravel:' . $sessionId);
}
Auth::logout();
return redirect()->route('main');
}
Он успешно вошел в систему, а также вышел из системы, но это не убивает весь сеанс на других устройствах.
Как мне решить эту проблему?
2 answers
Таким образом, проблема заключалась в опечатке в имени ключа redis,
для записи данных, используемых
$redis->sadd('users:sessions:'.$userId,Session::getId());
где префикс ключа 'users:sessions:'
и для получения данных используется
$redis->srem('user:sessions:' . $userId, $sessionId);
где префикс ключа 'user:sessions:'
Вот почему код не сработал и dd()
вернул пустой массив.
Итак, правильный код выглядит так
public function postSignIn(Request $request)
{
if (Auth::attempt(['email' => $request['email'], 'password' =>$request['password'] ]) ) {
$redis = \Redis::connection();
$userId=Session::getId();
$redis->sadd('user:sessions:'.$userId,Session::getId());
return redirect()->route('main');
}
return redirect()->back();
}
public function getLogout()
{
$redis = Redis::connection();
$userId=Session::getId();
$userSessions = $redis->smembers('user:sessions:' . $userId);
$currentSession = Session::getId();
foreach ($userSessions as $sessionId) {
if ($currentSession == $sessionId) {
continue;
}
$redis->srem('user:sessions:' . $userId, $sessionId);
$redis->del('laravel:' . $sessionId);
}
Auth::logout();
return redirect()->route('main');
}
У меня есть предложение/обходной путь для Вашей проблемы:
Работа с сеансами, которые не хранятся в базе данных, - это боль в **, поэтому вам нужно думать по-другому, чтобы решить проблему. Другим решением было бы записать идентификатор пользователя и время выхода пользователя из системы. Затем создайте промежуточное программное обеспечение, которое отключит пользователя, если подключение старше даты последнего выхода из системы. И это все.
Мой прототип выглядел бы так:
В строке метода postSignIn
ниже будет записан пользователь (сеанс) дата входа в систему: app('request')->session()->put('login_date', time());
В строке метода getLogout
ниже будет записана дата выхода пользователя из системы глобально:
\Cache::put('last_logout_'.\Auth::id(), time());
И последним штрихом будет промежуточное программное обеспечение с кодом, подобным этому:
if ($user = \Auth::user()) {
$login_date = app('request')->session()->get('login_date');
$last_logout_date = \Cache::get('last_logout_' . $user->id, time() + 100);
if ($login_date < $last_logout_date) {
\Auth::logout();
//redirect, error message...
}
}
Полный код:
Методы:
public function postSignIn(Request $request)
{
if (Auth::attempt(['email' => $request['email'], 'password' => $request['password']])) {
app('request')->session()->put('login_date', time());
return redirect()->route('main');
}
return redirect()->back();
}
public function getLogout()
{
\Cache::put('last_logout_' . \Auth::id(), time());
Auth::logout();
return redirect()->route('main');
}
Промежуточное программное обеспечение:
<?php
namespace App\Http\Middleware;
use Closure;
class LogoutIfExpired
{
public function handle($request, Closure $next, $guard = null)
{
if ($user = \Auth::user()) {
$login_date = app('request')->session()->get('login_date');
$last_logout_date = \Cache::get('last_logout_' . $user->id, time() + 100);
if ($login_date < $last_logout_date) {
\Auth::logout();
return redirect()->route('main');
}
}
return $next($request);
}
}