Question

Je souhaite empêcher plusieurs connexions dans une application PHP.

Tout d'abord, je crée l'état de connexion (actif, notactif) dans une table d'utilisateurs.

Lorsque l'utilisateur, un journal dans l'état de l'utilisateur sera défini sur «actif» et si l'utilisateur se connecte, l'état sera défini sur «Notactive». Lorsqu'un autre client essaie de se connecter à l'aide du même compte utilisateur, je vérifie la table utilisateur. Si l'utilisateur est toujours actif, la connexion d'erreur sera envoyée à l'utilisateur.

Le problème s'est produit, si l'utilisateur ferme le navigateur, l'état de la table utilisateur peut être mis à jour car l'utilisateur n'a pas cliqué de déconnexion.

Avez-vous une suggestion à ce sujet?

Était-ce utile?

La solution

(Veuillez noter que si la technique ici est encore quelque peu valide; les échantillons PHP ne doivent pas être copiés textuellement car il existe des moyens plus sûrs d'incorporer des valeurs fournies par l'utilisateur dans une requête SQL)


Au lieu de stocker si l'utilisateur est actif inactif, il est préférable de stocker un attribut qui peut être vérifié par rapport à l'utilisateur par action; Comme dans, chaque fois que l'utilisateur essaie de faire quelque chose qui nécessite une authentification, il vérifiera que cet attribut correspond avant son continu.

Je vous recommande de faire ce qui suit;

Tout d'abord, créez un hachage pour identifier uniquement l'utilisateur chaque fois qu'il se connecte. J'imagine qu'un sha1 de time() serait suffisant pour éviter les collisions. Quoi que vous choisissiez, assurez-vous qu'il est suffisamment varié pour qu'un autre utilisateur se connecte à avoir une chance incroyablement faible de recevoir le même hachage (par exemple, ne pas hacher l'adresse IP ou l'agent utilisateur du navigateur, car ceux-ci ne sont pas variés suffisant).

Deuxièmement, stockez ce hachage dans votre base de données et dans l'utilisateur session Au moment de la connexion. Le faisant effectivement «se déconnectera» de l'utilisateur précédent, car le hachage devrait être différent à chaque fois que quelqu'un se connecte.

Étant donné que nous utilisons des sessions, un cookie doit être automatiquement placé dans le navigateur de l'utilisateur qui contiendra un ID unique qui identifie l'utilisateur à ses données de session. Le contenu du cookie n'est pas vraiment préoccupant.

Ensuite, créez une fonction appelée authenticateUser() ou similaire, qui sera appelé au début de chaque script pour s'assurer que l'utilisateur est authentifié. Ce script doit interroger la base de données, vérifiant si un utilisateur avec l'ID de votre utilisateur a un hachage qui correspond au hachage de votre utilisateur.

Par exemple:

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

Ensuite, nous passons simplement authenticateUser() les utilisateurs ID, hash (selon vos données de session) et un database link (Pour une connexion de base de données, vous devrez avoir ouvert plus tôt).

Si authenticateUser() Retour true, l'utilisateur est authentifié. Si false, l'utilisateur n'est pas ou la base de données n'est pas disponible ou il y a une erreur SQL.

Veuillez noter cependant que cela augmentera votre chargement de serveur car une demande de base de données est envoyée une fois par demande de page. Ce n'est probablement pas si sage de le faire sur des projets géants où des milliers de personnes se connectent à tout moment. Je suis sûr que quelqu'un peut suggérer des améliorations.

De plus, attendre que le cookie expire n'est pas le meilleur moyen de forcer les personnes qui ont été inactives pour vous déconnecter, car vous ne devriez jamais faire confiance aux cookies. Au lieu de cela, vous pouvez ajouter une colonne appelée last_active que vous pouvez mettre à jour chaque fois que l'utilisateur est authentifié. Cela augmentera également la charge du serveur, mais vous permettra de remplacer manuellement hash Pour les utilisateurs qui ont été inactifs pendant 3 heures.

Autres conseils

Voici une solution qui n'a pas nécessiter une constante accès à la base de données travailler...

(qui évitera l'exigence de vérifier la session_id () par rapport à la valeur de la base de données chaque fois que vous demandez / actualisez une page, soulageant la contrainte DB / serveur) ...

1. En connexion, saisissez la session préexistante stockée dans la base de données pour cet utilisateur et faites-le:

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

2. Commencez ensuite une nouvelle session et enregistrez cette nouvelle session_id dans la base de données, en remplissant la précédente. Cela déconnectera la session précédente sur cet utilisateur s'il y en a un actif (enregistrer efficacement l'autre gars en utilisant ce compte).

Essayez-le et faites-moi savoir si cela fait l'affaire !!

Vous pouvez modifier votre modèle afin que seul l'utilisateur le plus récent puisse être connecté.

Si vous enregistrez l'ID de session le plus récent vu pour chaque utilisateur, lorsqu'ils se connectent une deuxième fois, vous pouvez jeter toute session existante, les enregistrer efficacement.

Pour un utilisateur normal, les choses semblent «fonctionner simplement». Si vous souhaitez empêcher les utilisateurs «anormaux» de distribuer leurs informations d'identification de connexion, cela devrait être dissuasif.

Ce que vous devez faire, c'est vérifier s'ils ont été actifs au cours des dernières minutes lorsqu'ils essaient de vous connecter. Cela pourrait être fait avec un timbre Lastonline et devrait être défini sur chaque demande de page dans la table d'utilisateurs.

Si ce n'est pas fait avec JavaScript, vous pouvez vérifier, lors de la connexion, si l'utilisateur était actif les 15 dernières minutes. Sinon, vous pouvez vous connecter en tant que nouvel utilisateur.

Vous pouvez également le faire avec JavaScript. Faites un appel Ajax qui tire toutes les minutes environ.

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

Laissez cet appel passer à un script qui modifiera le tampon Lastonline dans la base de données de l'utilisateur. Lorsque vous essayez de vous connecter, vous vérifiez la base de données de l'utilisateur si le timbre Lastonline a dépassé la minute et que vous avez votre chèque si vous pouvez vous connecter. Cela vous aidera lorsque vous serez sur la page, mais vous n'êtes pas actif au cours des 15 dernières minutes et vous ne voulez pas que quelqu'un d'autre se connecte.

Vous devez créer un ID unique et stocker cela dans une base de données. Ce que j'ai fait, c'est aussi créer. J'en stocke une dans une variable de session et je l'utilise pour empêcher le détournement de session et une autre dans une base de données pour éviter plusieurs connexions. Le code suivant créera un ID unique:

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

Si l'ID unique ne correspond pas, vous enregistrez simplement l'utilisateur.

L'utilisation de JavaScript du côté client afin de suivre les connectés à l'utilisateur n'est pas fiable.

Vous pouvez obtenir le même résultat en créant simplement un champ LastlogIndate dans la base de données et en le mettant à la mise à jour avec le dernier horodatage de connexion de l'utilisateur.

À chaque tentative de connexion, si maintenant () - $ lastlogIndate> PredEfined_timeout, vous devez accepter la nouvelle connexion, sinon la refuser.

Cette solution est similaire à celle de programme Il ne vous oblige pas à accéder à la base de données sur chaque page et ne verrouille pas l'utilisateur après avoir échoué.

Ajoutez un champ pour SessionID à votre table utilisateur dans la base de données.

Définissez le gestionnaire de session par défaut avant d'appeler session_start () (nécessaire pour que la ligne de code suivante fonctionne):

session_set_save_handler(new \SessionHandler());

À chaque connexion réussie, récupérez le $ SessionID stocké à partir de la base de données. Détruisez l'ancienne session avec:

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

Obtenez le nouvel identifiant de session avec:

$sessionID = session_id();

Stockez le nouvel ID de session dans la base de données.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top