Frage

Ich möchte mehrere Anmeldungen in einer PHP -Anwendung verhindern.

Zunächst erstelle ich in einer Benutzertabelle einen Anmeldestatus (aktiv, nicht aktiv).

Wenn der Benutzer ein Protokoll im Benutzerstatus auf "Active" festgelegt wird und der Benutzer den Status auf "Notactactive" anmeldet. Wenn sich ein anderer Client mit demselben Benutzer mit demselben Benutzer anmelden, überprüfe ich die Benutzertabelle. Wenn der Benutzer weiterhin aktiv ist, wird die Fehleranmeldung an den Benutzer gesendet.

Das Problem trat auf, wenn der Benutzer den Browser schließt, kann der Status in der Benutzertabelle aktualisiert werden, da der Benutzer nicht auf Anmeldung klickt.

Haben Sie einen Vorschlag dazu?

War es hilfreich?

Lösung

(Bitte beachten Sie, dass die Technik hier zwar noch etwas gültig ist; die PHP-Proben sollten nicht wörtlich kopiert werden, da es sicherere Mittel gibt, um benutzerversorgte Werte in eine SQL-Abfrage einzubeziehen)


Anstatt zu speichern, ob der Benutzer aktiv inaktiv ist, ist es besser, ein Attribut zu speichern, das auf der Basis pro Aktion gegen den Benutzer überprüft werden kann. Jedes Mal, wenn der Benutzer versucht, etwas zu tun, das eine Authentifizierung erfordert, wird er überprüfen, ob dieses Attribut entspricht, bevor es fortgesetzt wird.

Ich empfehle Ihnen, Folgendes zu tun.

Erstellen Sie zunächst einen Hash, um den Benutzer einzigartig zu identifizieren, wenn er sich anmeldet. Ich würde mir vorstellen, dass a sha1 von time() würde ausreichen, um Kollisionen zu vermeiden. Was auch immer Sie wählen, stellen Sie sicher, dass es so unterschiedlich ist, dass ein anderer Benutzer eine unglaublich geringe Chance hat, dasselbe Hash zu empfangen genügend).

Zweitens, speichern Sie diesen Hash in Ihrer Datenbank und im Benutzer des Benutzers Sitzung Zum Zeitpunkt der Anmeldung. Wenn Sie dies tun, melden Sie sich den vorherigen Benutzer effektiv an, da der Hash jedes Mal anders sein sollte, wenn jemand sich anmeldet.

Da wir Sitzungen verwenden, sollte ein Cookie automatisch in den Browser des Benutzers platziert werden, der eine eindeutige ID enthält, die den Benutzer für seine Sitzungsdaten identifiziert. Der Inhalt des Keks ist nicht wirklich von Sorge.

Erstellen Sie als nächstes eine Funktion namens namens authenticateUser() oder ähnlich, das zu Beginn jedes Skripts aufgerufen wird, um sicherzustellen, dass der Benutzer authentifiziert wird. Dieses Skript sollte die Datenbank abfragen und prüfen, ob ein Benutzer mit der ID Ihres Benutzers einen Hash hat, der dem Hash Ihres Benutzers entspricht.

Zum Beispiel:

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

Dann passieren wir einfach authenticateUser() der Benutzer ID, hash (per Ihre Sitzungsdaten) und a database link (Für eine Datenbankverbindung müssen Sie früher geöffnet haben).

Wenn authenticateUser() kehrt zurück true, Der Benutzer ist authentifiziert. Wenn false, Der Benutzer ist nicht oder die Datenbank ist nicht verfügbar oder es gibt einen SQL -Fehler.

Bitte beachten Sie jedoch, dass dies Ihr Serverlast erhöht, da eine Datenbankanforderung einmal pro Seitenanforderung gesendet wird. Es ist wahrscheinlich nicht allzu klug, dies bei riesigen Projekten zu tun, bei denen sich zu jeder Zeit Tausende von Menschen anmelden. Ich bin sicher, jemand kann Verbesserungen vorschlagen.

Das Warten auf den Auslauf des Keks ist nicht der beste Weg, um Menschen zu zwingen, die inaktiv waren, sich abzuloggen, da Sie niemals Keksen vertrauen sollten. Stattdessen können Sie in einer Spalte mit dem Namen last_active Was Sie jedes Mal aktualisieren können, wenn der Benutzer authentifiziert wird. Dies erhöht auch die Serverlast, ermöglicht es Ihnen jedoch, abgestandene Protokoll-Ins manuell zu überschreiben, indem Sie das entfernen hash Für Benutzer, die beispielsweise 3 Stunden inaktiv waren.

Andere Tipps

Hier ist eine Lösung, die nicht Konstant erfordern Datenbankzugriff arbeiten...

(Dadurch werden die Anforderung vermieden, die Session_id () bei jedem Antrag/Aktualisieren einer Seite mit dem Datenbankwert zu überprüfen, um DB/Server -Spannung zu lindern) ...

1. Geben Sie bei der Login die bereits bestehende Sitzung, die in der DB für diesen Benutzer gespeichert ist, und tun Sie dies:

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

2. Starten Sie dann eine neue Sitzung und speichern Sie diese neue Session_ID in der Datenbank, um die vorherige zu überschreiben. Dadurch wird die vorherige Sitzung bei diesem Benutzer abgelehnt, wenn es einen aktiv gibt (effektiv den anderen Typen mit diesem Konto angemeldet).

Probieren Sie es aus und lassen Sie mich wissen, ob das den Trick macht !!

Sie können Ihr Modell ändern, damit nur der neueste Benutzer angemeldet werden kann.

Wenn Sie die aktuellste Sitzungs -ID für jeden Benutzer aufzeichnen, können Sie bei einem zweiten Mal eine aktuell vorhandene Sitzung abgeben und sie effektiv ausführen.

Für einen normalen Benutzer scheinen die Dinge "nur zu funktionieren". Wenn Sie verhindern möchten, dass "abnormale" Benutzer ihre Anmeldeinformationen verteilen, sollte dies als Anreiz dienen.

Was Sie tun sollten, ist zu überprüfen, ob sie in den letzten einigen Minuten aktiv waren, als sie sich anmelden. Dies kann mit einem LastOnline -Stempel erfolgen und sollte auf jeder Seitenanforderung in der Benutzertabelle festgelegt werden.

Wenn Sie nicht mit JavaScript fertiggestellt werden, können Sie sich beim Anmelden überprüfen, wenn der Benutzer in den letzten 15 Minuten aktiv war. Wenn nicht, können Sie sich als neuer Benutzer anmelden.

Sie können es auch mit JavaScript tun. Machen Sie einen Ajax -Anruf, der jede Minute oder so feuert.

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

Lassen Sie diesen Anruf zu einem Skript gehen, das den LastOnline -Stempel im Benutzer DB bearbeitet. Beim Versuch, sich anzumelden, überprüfen Sie den Benutzer DB, wenn der LastOneline -Stempel die Minute überschritten hat und Sie überprüfen, ob Sie sich möglicherweise anmelden. Dies hilft, wenn Sie auf der Seite sind, aber in den letzten 15 Minuten nicht aktiv sind und Sie möchten nicht, dass sich jemand anderes anmeldet.

Sie müssen eine eindeutige ID erstellen und diese in einer Datenbank speichern. Was ich auch getan habe, war auch geschaffen. Ich speichere eine in einer Sitzungsvariablen und benutze diese, um die Hijacking von Sitzungen und eine in einer Datenbank zu verhindern, um mehrere Anmeldungen zu verhindern. Der folgende Code erstellt eine eindeutige ID:

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

Wenn die eindeutige ID nicht übereinstimmt, protokollieren Sie den Benutzer einfach heraus.

Die Verwendung von Client -Seite JavaScript, um im Benutzer protokolliert zu verfolgen, ist unzuverlässig.

Sie können das gleiche Ergebnis erzielen, indem Sie einfach ein LastLogindat -Feld im DB erstellen und es mit dem letzten Anmeldestempel des Benutzers aktualisieren.

Bei jedem Anmeldeversuch, falls jetzt ()-$ lastLogindate> Prefined_timeout, sollten Sie das neue Login akzeptieren, sonst weigeren Sie ihn.

Diese Lösung ähnelt dem von Prograhammer, erfordert jedoch nicht, dass Sie mit Schaltsitzungen herumspielen. Sie müssen nicht auf jeder Seite auf die Datenbank zugreifen und den Benutzer nicht aussperrt, nachdem er sich nicht abgemeldet hat.

Fügen Sie Ihrer Benutzertabelle in der Datenbank ein Feld für SessionID hinzu.

Setzen Sie den Standard -Sitzungshandler, bevor Sie Session_start () aufrufen (erforderlich, damit die nächste Codezeile funktioniert):

session_set_save_handler(new \SessionHandler());

Rufen Sie bei jedem erfolgreichen Login die gespeicherte $ sessionID aus der Datenbank ab. Zerstöre die alte Sitzung mit:

(new \SessionHandler())->destroy($sessionID);

Holen Sie sich die neue Sitzungs -ID mit:

$sessionID = session_id();

Speichern Sie die neue Sitzungs -ID in der Datenbank.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top