2009-11-13 12 views
14

Desidero impedire più accessi in un'applicazione php.Come impedire accessi multipli nel sito Web di PHP

In primo luogo, ho creato lo stato di accesso (attivo, NotActive) in una tabella utente.

Quando l'utente A accede allo stato dell'utente verrà impostato su "attivo" e se l'utente si disconnette lo stato verrà impostato su "non attivo". Quando un altro client cerca di accedere utilizzando lo stesso account utente, controllo la tabella utente. Se l'utente è ancora attivo, l'accesso all'errore verrà inviato all'utente.

Il problema si è verificato, se l'utente chiude il browser lo stato nella tabella utente può essere aggiornato perché l'utente non ha fatto clic su Esci.

Avete qualche suggerimento su questo?

+0

Il bit di domanda reale di questo ("come posso disconnettere gli utenti che diventano inattivi?"), È stato chiesto qui prima (vedi http://stackoverflow.com/questions/247412/) –

risposta

17

Invece di memorizzare se l'utente è attivo \ inattivo, è meglio memorizzare alcuni attributi che possono essere controllati dall'utente per ogni azione; come in, ogni volta che l'utente prova a fare qualcosa che richiede l'autenticazione, controllerà che questo attributo corrisponda prima che proceda.

Si consiglia di effettuare le seguenti operazioni;

Innanzitutto, creare un hash per identificare univocamente l'utente ogni volta che si accede. Immagino che uno sha1 di time() sia sufficiente per evitare collisioni.Qualunque cosa scegliate, assicurarsi che sia abbastanza variato in modo che un altro utente login avrà un incredibilmente basso possibilità di ricevere lo stesso hash (ad esempio, non hash l'indirizzo IP o del browser user-agent, in quanto questi non sono variati abbastanza).

In secondo luogo, conservare questo hash nel database e l'utente del session al momento della log in. In questo modo si efficacemente 'log out' l'utente precedente, come l'hash dovrebbe essere diverso ogni volta che qualcuno accede.

Dal momento che stiamo usando le sessioni, un cookie deve essere posto automaticamente nel browser dell'utente che conterrà un ID univoco che identifica l'utente ai suoi dati di sessione. I contenuti del cookie non sono davvero preoccupanti.

Successivamente, creare una funzione denominata authenticateUser() o simile, che verrà richiamata all'inizio di ogni script per garantire che l'utente sia autenticato. Questo script dovrebbe interrogare il database, controllando se un utente con l'ID dell'utente ha un hash che corrisponde all'hash dell'utente.

Ad esempio:

function authenticateUser($id, $hash, $databaseLink) { 
    # SQL 
    $sql = 'SELECT EXISTS(
       SELECT 1 
       FROM `tbl_users` 
       WHERE `id` = \''.mysql_real_escape_string($id).'\' 
       AND `hash` = \''.mysql_real_escape_string($hash).'\' 
       LIMIT 1 
      );'; 

    # Run Query 
    if ($query = mysql_query($sql, $databaseLink)) { 
     # Get the first row of the results 
     # Assuming 'id' is your primary key, there 
     # should only ever be one row anyway.  
     $result = mysql_fetch_row($query); 

     # Casting to boolean isn't strictly necessary here 
     # its included to indicate the mysql result should 
     # only ever been 1 or 0. 
     return (bool)($result[0]); 
    } else { 
     # Query error :(
     return false; 
    } 
} 

Poi, abbiamo semplicemente passare authenticateUser() dell'utente ID, hash (per i dati di sessione) e una database link (per una connessione al database si dovrà aver aperto in precedenza).

Se authenticateUser() restituisce true, l'utente è autenticato. Se false, l'utente non è OR il database non è disponibile o c'è un errore SQL.

Si prega di notare, tuttavia, che questo aumenterà il carico del server come una richiesta di database viene inviata una volta per ogni richiesta di pagina. Probabilmente non è del tutto saggio farlo su progetti giganti in cui migliaia di persone si collegano in un dato momento. Sono sicuro che qualcuno può suggerire miglioramenti.

Inoltre, attendere che il cookie scada non è il modo migliore per forzare le persone che sono state inattive a disconnettersi, poiché non si dovrebbe mai fidarsi dei cookie. Invece, è possibile aggiungere in una colonna chiamata last_active che è possibile aggiornare ogni volta che l'utente è autenticato. Questo aumenterà anche il carico del server, ma vi permetterà di ignorare manualmente stantii log-in rimuovendo il hash per gli utenti che erano, diciamo, inattivo per 3 ore.

+0

nness - sarebbe sufficiente memorizzare il phpsessid nella tabella e $ _SESSION? Sto mostrando che quando lo stesso account si registra in un altro sistema, viene stabilito un nuovo phpsessid. –

+0

Immagino che potrebbe essere altrettanto adatto. Non dovrebbe essere troppo difficile da testare, accedi da un certo numero di dispositivi e osserva che quelli giusti sono stati disconnessi. –

+0

Sembra funzionare bene. Implementato nella mia sandbox dell'applicazione ieri e testato con alcuni sistemi sullo stesso account. Funziona piuttosto bene. –

6

Che cosa si dovrebbe fare è controllare se essi sono stati attivi degli ultimi minuti quando si cerca di effettuare il login. Questo potrebbe essere fatto con un timbro lastonline e dovrebbe essere impostato su ogni richiesta di pagina nella tabella utente.

Se non utilizzato con javascript è possibile controllare, al momento dell'accesso, se l'utente era attivo negli ultimi 15 minuti. Altrimenti puoi accedere come nuovo utente.

Si potrebbe anche farlo con javascript. Fai una chiamata ajax che spara ogni minuto circa.

<script> 
setInterval(function() { 
    // do the ajax call 
}, 60000); 
</script> 

Lascia andare questa chiamata a uno script che modificherà il timbro lastonline nel db dell'utente. Quando provi ad accedere, controlla l'utente db se il francobollo lastonline ha superato il minuto e hai il tuo assegno se puoi effettuare il login. Questo ti aiuterà quando sei sulla pagina ma non sei attivo negli ultimi 15 minuti e non vuoi che qualcun altro faccia il login.

+0

perché non è utile? Io non capisco –

+0

Non ero il downvoter, ma avere JavaScript sul lato client non è in alcun modo un garante che i visitatori verranno disconnessi dopo 60 secondi. Considerare anche cosa succede se l'utente chiude semplicemente la pagina. –

+0

Sarò un po 'd'aiuto pieno. ma, come se l'utente dovesse chiudere il browser ??? –

5

Si potrebbe modificare il modello in modo che solo l'utente più recente può essere registrato.

Se si registra il più recente id di sessione visti per ciascun utente, quando questi si collegano in un secondo tempo si può cestinare qualsiasi momento sessione esistente, registrandole in modo efficace.

per un utente normale, le cose sembrano "solo lavoro". Se si desidera impedire agli utenti "anormali" di distribuire le proprie credenziali di accesso, questo dovrebbe servire da disincentivo.

+0

Onestamente non ho ancora capito la tua risposta. E ti darò una domanda più specifica: D. Person_A cercano di effettuare il login utilizzando login user_a, lo stato dell'utente verrà impostato su attivo e quest'ultimo, Person_B vogliono provare accedere al webiste utilizzando User A. person_B non può essere accedere al web, perché user_a ancora attivo. 'Quando un account è ancora attivo, un altro utente non può accedere al sito Web utilizzando lo stesso utente' e il problema si è verificato. Se l'utente termina il browser. il browser non può inviare dati al server per eseguire l'azione di disconnessione. Quindi, lo stato sarà sempre attivo anche se l'utente non è più attivo. –

+2

Bene, quello che sto dicendo è che quando user_B si collega, user_A viene automaticamente disconnesso. Può esserci una buona ragione per cui vuoi impedire l'accesso di user_B, ma non hai chiarito il motivo per cui è preferibile. Il mio suggerimento risolve il problema dell'attesa di un timeout della sessione per consentire il re-login, impedendo comunque a un utente di effettuare il login due volte. –

0

Utilizzando JavaScript lato client al fine di monitorare il login utente è inaffidabile.

È possibile ottenere lo stesso risultato semplicemente creando un campo lastlogindate nel db e aggiornandolo con l'ultimo timestamp di accesso dell'utente.

Ad ogni tentativo di accesso, se ora() - $ lastlogindate> predefinito_timeout, è necessario accettare il nuovo accesso, altrimenti rifiutarlo.

1

È necessario creare un ID univoco e memorizzare che in un database. Anche quello che ho fatto è stato creare. Ne conservo uno in una variabile di sessione e lo utilizzo per impedire il dirottamento di sessione e un altro in un database per impedire accessi multipli. Il codice seguente consente di creare un ID univoco:

$unique_id = sha1('xzr4'.gethostbyaddr($_SERVER['REMOTE_ADDR']).$random_string.$_SERVER['HTTP_USER_AGENT'].'f8k2'); 

Se l'ID univoco non corrisponde, è sufficiente scollegare l'utente.

4

Ecco una soluzione che non richiedono costante accesso al database a lavorare ...

(che eviterà l'obbligo di verificare il session_id() contro il valore del database ogni volta che si richiede/aggiornamento una pagina, alleggerendo lo stress db/server) ...

1. Su login, afferrare il session_id pre-esistenti memorizzati nel DB per questo utente e fare questo:

session_id("the pre-existing session id in the database goes here"); 
session_start(); 
session_destroy(); 

2. quindi avviare una nuova sessione e salvare questo nuovo session_id al database, sovrascrivendo quello precedente . Questo disconnetterà la sessione precedente su questo utente se ce n'è uno attivo (disconnettendo in modo efficace l'altro usando questo account).

Provalo e fammi sapere se questo fa il trucco !!

+0

L'ho appena provato - funziona bene e senza stressare il server. Molto elegante - Grazie! – cronoklee

+0

ma per quanto riguarda la funzione session_regenerate_id()? perché l'ho usato periodicamente? quindi sembra che devo salvare/aggiornare l'ID rigenerato nel database e quindi fa lo stesso stress a db giusto? –

Problemi correlati