2009-11-13 13 views
14

Chcę zapobiec wielu loginów w aplikacji php.Jak zapobiec wielu logowaniom na stronie PHP

Najpierw tworzę status logowania (aktywny, nieaktywny) w tabeli użytkownika.

Gdy użytkownik A logujący się w statusie użytkownika zostanie ustawiony na "aktywny", a jeśli użytkownik wyloguje się, status zostanie ustawiony na "nieaktywny". Gdy inny klient próbuje zalogować się przy użyciu tego samego konta użytkownika, sprawdzam tabelę użytkowników. Jeśli użytkownik nadal jest aktywny, login błędu zostanie wysłany do użytkownika.

Wystąpił problem, jeśli użytkownik zamknie przeglądarkę, status w tabeli użytkowników może zostać zaktualizowany, ponieważ użytkownik nie kliknął przycisku wylogowania.

Czy masz jakieś sugestie na ten temat?

+0

Właściwy bit tego pytania ("jak mogę wylogować użytkowników, którzy stają się nieaktywni?"), Został tu wcześniej zapytany (patrz http://stackoverflow.com/questions/247412/) –

Odpowiedz

17

Zamiast zapisywać, czy użytkownik jest aktywny \ nieaktywny, lepiej jest przechowywać pewne atrybuty, które mogą być sprawdzane dla użytkownika na podstawie działania; podczas gdy za każdym razem, gdy użytkownik próbuje zrobić coś, co wymaga uwierzytelnienia, sprawdza, czy ten atrybut jest zgodny, zanim zacznie działać.

Polecam wykonać następujące czynności;

Najpierw utwórz skrót, aby jednoznacznie zidentyfikować użytkownika przy każdym logowaniu. Wyobrażam sobie, że wystarczy sha1 z time(), aby uniknąć kolizji.Bez względu na to, co wybierzesz, upewnij się, że jest wystarczająco zróżnicowany, aby inny użytkownik logujący się miał niewiarygodnie niskie szanse na otrzymanie tego samego skrótu (na przykład, nie mieszając adresu IP lub przeglądarki użytkownika, ponieważ nie są one różne dość).

Po drugie, nie przechowuj wartości mieszania w bazie danych oraz w instrukcji session w momencie logowania. Robi to skutecznie będzie „wylogowanie” poprzedniego użytkownika, jak hash powinna być inna za każdym razem ktoś loguje się.

Ponieważ używamy sesji, plik cookie powinien automatycznie zostać umieszczony w przeglądarce użytkownika, który będzie zawierał unikatowy identyfikator identyfikujący użytkownika do jego danych sesji. Zawartość pliku cookie nie stanowi problemu.

Następnie należy utworzyć funkcję o nazwie authenticateUser() lub podobną, która będzie wywoływana na początku każdego skryptu, aby zapewnić uwierzytelnienie użytkownika. Ten skrypt powinien wysłać zapytanie do bazy danych, sprawdzając, czy użytkownik z identyfikatorem użytkownika ma skrót, który jest zgodny z hashem użytkownika.

Na przykład:

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

Następnie, po prostu przejść authenticateUser() użytkownikowi na ID, hash (za swoich danych sesyjnych) i database link (dla połączenia z bazą danych będzie trzeba mieć otwarte wcześniej).

Jeśli authenticateUser() wróci true, użytkownik zostanie uwierzytelniony. Jeśli false, użytkownik nie jest LUB baza danych jest niedostępna lub jest błąd SQL.

Należy jednak pamiętać, że zwiększy to obciążenie serwera, ponieważ żądanie bazy danych jest wysyłane raz na żądanie strony. Prawdopodobnie nie jest to mądre, aby zrobić to w gigantycznych projektach, w których tysiące osób loguje się w danym momencie. Jestem pewien, że ktoś może sugerować ulepszenia.

Również czekanie na wygaśnięcie pliku cookie nie jest najlepszym sposobem zmuszenia osób nieaktywnych do wylogowania się, ponieważ nigdy nie należy ufać ciasteczkom. Zamiast tego możesz dodać kolumnę o nazwie last_active, którą możesz zaktualizować za każdym razem, gdy użytkownik jest uwierzytelniany. Spowoduje to również zwiększenie obciążenia serwera, ale pozwoli na ręczne zastąpienie nieaktualnych logowań przez usunięcie hash dla użytkowników, którzy byli, powiedzmy, nieaktywni przez 3 godziny.

+0

nness - czy wystarczy zapisać phpsessid w tabeli i $ _SESSION? Pokazuję, że kiedy to samo konto loguje się w innym systemie, zostaje ustanowiony nowy phpsessid. –

+0

Wyobrażam sobie, że to może być odpowiednie. Nie powinno być zbyt trudne do przetestowania, zalogować się z wielu urządzeń i obserwować, czy te właściwe są wylogowane. –

+0

Wygląda na to, że działa dobrze. Wdrożone w mojej aplikacji sandbox wczoraj i przetestowane z kilkoma systemami na tym samym koncie. Działa całkiem dobrze. –

6

Co należy zrobić, to sprawdzić, czy były aktywne przez ostatnie kilka minut podczas próby logowania. Można to zrobić za pomocą ostatniej pieczątki i należy ją ustawić na każdym żądaniu strony w tabeli użytkownika.

Jeśli nie zrobisz tego przy pomocy javascripta, po zalogowaniu możesz sprawdzić, czy użytkownik był aktywny przez ostatnie 15 minut. Jeśli nie, możesz zalogować się jako nowy użytkownik.

Można to również zrobić za pomocą javascript. Wykonaj wywołanie ajax, które odpala co minutę.

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

Pozwól temu połączeniu przejść do skryptu, który edytuje znaczek ostatniej linii w db użytkownika. Podczas próby zalogowania się sprawdzasz użytkownika db, jeśli znaczek ostatniej linii przekroczył minutę i masz sprawdzenie, czy możesz się zalogować. Pomoże to, gdy będziesz na stronie, ale nie będziesz aktywny przez ostatnie 15 minut i nie chcesz, aby ktoś inny się zalogował.

+0

dlaczego to nie jest pomocne? Nie rozumiem tego. –

+0

Nie byłem downvoter, ale posiadanie JavaScript po stronie klienta wcale nie jest gwarantem, że użytkownicy zostaną wylogowani po 60 sekundach. Zastanów się również, co się stanie, jeśli użytkownik po prostu zamknie stronę. –

+0

Będę trochę pomóc w pełni. ale, jeśli użytkownik wypowie przeglądarkę ??? –

5

Można zmienić swój model tak, że tylko najnowsze użytkownik może być zalogowany.

Jeśli nagrywasz najnowszą identyfikator sesji widoczny dla każdego użytkownika, po zalogowaniu się po raz drugi można kosza dowolny aktualnie istniejącej sesji, skutecznie je wylogowując.

Dla zwykłego użytkownika rzeczy wydają się "po prostu działać". Jeśli nie chcesz, aby "nienormalni" użytkownicy rozpowszechniali swoje dane logowania, powinno to zniechęcać.

+0

Szczerze mówiąc nie zdobyłem jeszcze twojej odpowiedzi. I dam ci bardziej szczegółowe pytanie: D. Person_A spróbuj się zalogować przy pomocy User_A login, status użytkownika zostanie ustawiony na aktywny , a następnie Person_B chce spróbować zalogować się do strony za pomocą User A. osoba_B nie może zalogować się do sieci, ponieważ User_A jest nadal aktywna. 'Gdy konto jest nadal aktywne, inne osoby nie mogą zalogować się do witryny przy użyciu tego samego użytkownika' i wystąpił problem. Jeśli użytkownik zakończy przeglądarkę. przeglądarka nie może wysyłać danych do serwera w celu wykonania czynności wylogowania. Tak więc stan będzie zawsze aktywny, mimo że użytkownik nie będzie już aktywny. –

+2

Cóż, mówię, że gdy użytkownik loguje się, user_A jest automatycznie wylogowywany. Może istnieć dobry powód, dla którego chcesz zapobiec logowaniu użytkownika, ale nie wyjaśniłeś, dlaczego jest to lepsze. Moja sugestia omija problem oczekiwania na przekroczenie limitu czasu sesji, aby umożliwić ponowne logowanie, uniemożliwiając jednocześnie dwukrotne logowanie użytkownika. –

0

Używanie javascript po stronie klienta do śledzenia zalogowanego użytkownika jest niewiarygodne.

Ten sam wynik można uzyskać, tworząc po prostu pole ostatniego logowania w bazie danych i aktualizując je przy użyciu ostatniego znacznika czasu logowania użytkownika.

Przy każdej próbie logowania, jeśli teraz() - $ lastlogindate> predefined_timeout, powinieneś zaakceptować nowy login, w przeciwnym razie odmów.

1

Należy utworzyć unikalny identyfikator i zapisać go w bazie danych. To, co zrobiłem, to też stworzyłem. Przechowuję jeden w zmiennej sesji i używam go, aby zapobiec przechwytywaniu sesji, a innym w bazie danych, aby zapobiec wielu loginów. Poniższy kod utworzy unikalny identyfikator:

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

Jeśli unikalny identyfikator nie pasuje, po prostu wyloguj użytkownika.

4

Oto rozwiązanie, które nie wymagają stałej dostęp do bazy danych do pracy ...

(co pozwoli uniknąć obowiązku sprawdzenia session_id() w stosunku do wartości bazy danych za każdym razem gdy żądanie/odświeżania strona, zmniejszając stres na serwerze/serwerze) ...

1. Po zalogowaniu chwycić istniejących uprzednio SESSION_ID przechowywane w DB dla tego użytkownika i zrobić to:

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

2. Następnie rozpocząć nową sesję i zapisać nową SESSION_ID do bazy danych, zastępując poprzednią . Spowoduje to wylogowanie poprzedniej sesji tego użytkownika, jeśli jest jedna aktywna (skutecznie wylogowujesz drugiego gościa korzystającego z tego konta).

Spróbuj i daj mi znać, jeśli to wystarczy!

+0

Po prostu próbowałem - działa ładnie i bez obciążania serwera. Bardzo elegancko - dzięki! – cronoklee

+0

, ale co z funkcją session_regenerate_id()? ponieważ używałem tego okresowo? więc wydaje się, że muszę zapisać/zaktualizować ponownie wygenerowany identyfikator do bazy danych, a co za tym idzie taki sam nacisk na db? –

Powiązane problemy