2016-05-24 15 views
7

Gdy użytkownik wylogował się z urządzenia perpikcyjnego, chcę się wylogować ze wszystkich urządzeń, na których się zalogował do tej pory. Jak to robię w Laravel.Laravel 5.2 - Jak wylogować użytkownika ze wszystkich jego urządzeń

Użyłem Redis do przechowywania identyfikatora użytkownika w sesji instalując "predis/predis": "~ 1.0"

i tu jest mój kontroler dla signin i wylogowania:

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

To powodzeniem dostać zalogowany i wylogowany, ale nie zabija całej sesji na innych urządzeniach.

Jak rozwiązać problem?

+0

Spróbuj zmienić położenie linii na funkcję getLogout: $ redis-> Srem; ('USER:: sesje' $ USERID $ sessionid). $ redis-> del ('laravel:'. $ sessionId); –

+0

Występuje problem z moim Redis Connection tak samo Błąd pojawia się po zmianie tych linii. – Hola

+0

hm Myślę, że powinieneś użyć '$ userId = Auth :: user() -> id;' zamiast '$ userId = Session :: getId();' ponieważ second daje ci identyfikator sesji, ale nie użytkownika Myślę, że problem, w ten sposób w twoim przypadku zapisujesz za każdym razem tylko jeden identyfikator sesji – dyachenko

Odpowiedz

3

więc problem był z typo w Redis nazwę klucza, dla zapisu danych stosowany $redis->sadd('users:sessions:'.$userId,Session::getId()); gdzie prefiks klucza 'users:sessions:' i do uzyskania danych użytych $redis->srem('user:sessions:' . $userId, $sessionId); gdzie prefiks klucza 'user:sessions:' To dlatego kod nie zadziałał, a dd() zwrócił pustą tablicę.

więc poprawny kod wygląda następująco

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

Mam propozycję dla Twojego/obejście problemu:

Praca z sesjami, które nie są przechowywane w bazie danych jest ból w sposób **, więc trzeba myśleć inaczej w celu rozwiązania problemu. Innym rozwiązaniem byłoby zapisanie identyfikatora i czasu użytkownika podczas wylogowywania użytkownika. Następnie utwórz oprogramowanie pośrednie, które rozłączy użytkownika, jeśli połączenie jest starsze niż data ostatniego wylogowania. I to wszystko.


Mój prototyp będzie wyglądać tak: metoda
W postSignIn linia poniżej rejestruje użytkownika (sesja) data logowanie: app('request')->session()->put('login_date', time());

W metodzie getLogout linii poniżej rejestruje użytkownika datę wylogowania globalnie: \Cache::put('last_logout_'.\Auth::id(), time());

Ostatnim dotknięciem byłoby oprogramowanie pośrednie z kodem podobnym do tego:

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... 
    } 
} 

Pełny kod:

Metody:

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

Middleware:

<?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); 
    } 
} 
+0

możesz mi pomóc z pełnym kodem? jeśli to możliwe .. Może b Nie dostaję tego, co naprawdę chciałeś powiedzieć! – Hola

+0

@ x69 Nie ma problemu, dołączyłem odpowiedź. –

+0

Upewnij się także, że Twoja 'QUEUE_DRIVER' nie jest' sync'. –

Powiązane problemy