2016-05-24 27 views
7

Quando un utente si è disconnesso da un dispositivo perticulare, voglio disconnettermi da tutti i dispositivi che ha effettuato il login fino ad ora. Come lo faccio a Laravel.Laravel 5.2 - Come disconnettere un utente da tutti i suoi dispositivi

ho usato Redis per mantenere l'ID utente nella sessione con l'installazione "Predis/Predis": "~ 1.0"

Ed ecco il mio controller per SignIn e Esci:

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

E 'ottenere con successo loggato e anche disconnesso ma non uccide tutte le sessioni su altri dispositivi.

Come posso risolvere il problema?

+0

Basta provare a cambiare la posizione della linea sulla funzione getLogout: $ riscoperto> Srem; ('utente:: le sessioni di' $ userId, $ sessionId.) $ redis-> del ('laravel:'. $ sessionId); –

+0

C'è un problema con la mia connessione redis così lo stesso errore che ricevo dopo aver cambiato quelle linee. – Hola

+0

hm Penso che dovresti usare '$ userId = Auth :: user() -> id;' invece di '$ userId = Session :: getId();' perché secondo ti dà id di sessione ma non utente Penso che il problema, con questo così nel tuo caso si salva ogni volta solo un ID di sessione – dyachenko

risposta

3

Così problema è stato con errore di battitura nel nome della chiave Redis, per scrittura dati utilizzati $redis->sadd('users:sessions:'.$userId,Session::getId()); dove prefisso chiave 'users:sessions:' e per ottenere i dati utilizzati $redis->srem('user:sessions:' . $userId, $sessionId); dove prefisso chiave 'user:sessions:' Ecco perché il codice non ha funzionato e dd() ha restituito l'array vuoto.

codice in modo corretto è simile al seguente

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

Ho un suggerimento/soluzione per il problema:

Lavorare con le sessioni che non vengono memorizzati nel database è il dolore in un **, quindi bisogna pensare in modo diverso al fine di risolvere il problema. La soluzione diversa sarebbe quella di registrare l'ID utente e l'ora, quando si disconnette l'utente. Quindi creare il middleware che disconnetterà l'utente se la connessione è precedente alla data dell'ultimo logout. E questo è tutto.


mio prototipo apparirebbe in questo modo:
In postSignIn metodo riga sotto registrerà utente (sessione) Data login: app('request')->session()->put('login_date', time());

In getLogout linea metodo seguito registrerà utente Data disconnessione a livello globale: \Cache::put('last_logout_'.\Auth::id(), time());

E il tocco finale sarebbe il middleware con codice simile a questo:

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

codice completo:

Metodi:

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

puoi aiutarmi con il codice completo? se possibile..Mah non riesco a ottenere ciò che volevi dire veramente! – Hola

+0

@ x69 Nessun problema, ho aggiunto la mia risposta. –

+0

Assicurati inoltre che il tuo 'QUEUE_DRIVER' non sia' sync'. –

Problemi correlati