2009-11-13 70 views
14

Quiero evitar varios inicios de sesión en una aplicación php.Cómo prevenir múltiples inicios de sesión en el sitio web de PHP

Primero, creo el estado de inicio de sesión (activo, notactivo) en una tabla de usuario.

Cuando el usuario A registra el estado del usuario se establecerá en 'activo', y si el usuario cierra la sesión, el estado se establecerá en 'notactive'. Cuando otro cliente intenta iniciar sesión usando la misma cuenta de usuario, verifico la tabla de usuarios. Si el usuario aún está activo, el inicio de sesión de error se enviará al usuario.

El problema ocurrió, si el usuario cierra el navegador, el estado en la tabla de usuario se puede actualizar porque el usuario no hizo clic en cerrar sesión.

¿Tiene alguna sugerencia al respecto?

+0

El bit de pregunta real de esto ("¿cómo puedo desconectar a los usuarios que se vuelven inactivos?"), Se ha preguntado aquí anteriormente (ver http://stackoverflow.com/questions/247412/) –

Respuesta

17

En lugar de almacenar si el usuario está activo \ inactivo, es mejor almacenar algún atributo que pueda verificarse contra el usuario por acción; como en, cada vez que el usuario intenta hacer algo que requiere autenticación, verificará que este atributo coincida antes de continuar.

Le recomiendo que haga lo siguiente;

Primero, cree un hash para identificar al usuario de manera única cada vez que inicie sesión. Imagino que un sha1 de time() sería suficiente para evitar colisiones.Elija lo que elija, asegúrese de que sea lo suficientemente variado para que otro usuario que inicie sesión tenga una probabilidad increíblemente baja de recibir el mismo hash (por ejemplo, no cifre la dirección IP o el user-agent del navegador, ya que estos no son variados). suficiente).

En segundo lugar, almacenar este hash en su base de datos y en el usuario de session en el momento de iniciar sesión. Si lo hace, efectivamente 'desconectarse' el usuario anterior, ya que el hash debe ser diferente cada vez que alguien abre una sesión.

Dado que estamos utilizando sesiones, una cookie debe colocarse automáticamente en el navegador del usuario que contendrá una identificación única que identifica al usuario con sus datos de sesión. El contenido de la cookie no es realmente preocupante.

A continuación, cree una función llamada authenticateUser() o similar, que se invocará al inicio de cada secuencia de comandos para garantizar que el usuario esté autenticado. Este script debe consultar la base de datos, verificando si un usuario con su ID de usuario tiene un hash que coincida con el hash de su usuario.

Por ejemplo:

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

Luego, simplemente pasan authenticateUser() del usuario ID, hash (por sus datos de sesión) y una database link (para una conexión de base de datos, tendrá que haber abierto antes).

Si authenticateUser() devuelve true, el usuario está autenticado. Si false, el usuario no está O la base de datos no está disponible o hay un error de SQL.

Sin embargo, tenga en cuenta que esto aumentará la carga de su servidor ya que una solicitud de base de datos se envía una vez por solicitud de página. Probablemente no sea tan acertado hacer esto en proyectos gigantescos en los que miles de personas inician sesión en un momento dado. Estoy seguro de que alguien puede sugerir mejoras.

Además, esperar a que caduque la cookie no es la mejor manera de obligar a las personas que han estado inactivas a desconectarse, ya que nunca debe confiar en las cookies. En su lugar, puede agregar una columna llamada last_active que puede actualizar cada vez que el usuario se autentica. Esto también aumentará la carga del servidor, pero le permitirá anular manualmente el inicio de sesión obsoleto al eliminar el hash para usuarios que estuvieron, por ejemplo, inactivos durante 3 horas.

+0

nness - ¿Sería suficiente almacenar el phpsessid en la tabla y $ _SESSION? Estoy mostrando que cuando la misma cuenta inicia sesión en un sistema diferente, se establece un nuevo phpsessid. –

+0

Me imagino que podría ser tan adecuado. Además, no debe ser demasiado difícil de probar, inicie sesión desde varios dispositivos y observe si se cierran las sesiones correctas. –

+0

Parece que funciona bien. Implementado ayer en mi sandbox de aplicaciones y probado con algunos sistemas en la misma cuenta. Funciona bastante bien –

6

Lo que debe hacer es comprobar si han estado activos durante los últimos minutos al intentar iniciar sesión. Esto se puede hacer con un último sello en línea y se debe configurar en cada solicitud de página en la tabla de usuario.

Si no se hace con javascript, puede comprobar, al iniciar sesión, si el usuario estuvo activo los últimos 15 minutos. Si no, puede iniciar sesión como el nuevo usuario.

También podría hacerlo con javascript. Haga una llamada ajax que dispare cada minuto más o menos.

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

Deje que esta llamada vaya a un script que editará el último sello en línea en el usuario db. Al intentar iniciar sesión, verifique el usuario db si el último sello en línea ha excedido el minuto y tiene su cheque si puede iniciar sesión. Esto te ayudará cuando estés en la página pero no estás activo los últimos 15 minutos y no quieres que alguien más inicie sesión.

+0

¿por qué no es útil? No lo entiendo –

+0

Yo no era el que menospreciaba, pero tener JavaScript en el lado del cliente de ninguna manera es un garante de que los visitantes serán desconectados después de 60 segundos. También considere lo que sucede si el usuario simplemente cierra la página. –

+0

Voy a ayudar un poco por completo. pero, ¿cómo si el usuario termina el navegador ??? –

5

Usted podría cambiar su modelo de modo que sólo el usuario más reciente puede ser conectado.

Si graba la última sesión de identificación visto para cada usuario, cuando inician sesión en un segundo tiempo se papelera cualquier momento sesión existente, lográndolos de forma efectiva.

Para un usuario normal, las cosas parecen "simplemente funcionar". Si desea evitar que los usuarios "anormales" distribuyan sus credenciales de inicio de sesión, esto debería servir como desincentivo.

+0

Honestamente, aún no he entendido su respuesta. Y le daré una pregunta más específica: D. Person_A intentar iniciar sesión utilizando el inicio de sesión User_A, el estado del usuario se establecerá en y el último, Person_B desea intentar iniciar sesión en el sitio web utilizando el usuario A. person_B no puede iniciar sesión en la web porque User_A todavía está activo. 'Cuando una cuenta aún está activa, otras personas no pueden iniciar sesión en el sitio web utilizando el mismo usuario' y, el problema ocurrió. Si el usuario termina el navegador. el navegador no puede enviar datos al servidor para realizar la acción de cierre de sesión. Por lo tanto, el estado siempre estará activo aunque el usuario ya no esté activo. –

+2

Bueno, lo que digo es que cuando el usuario_B inicia sesión, el usuario_A se desconecta automáticamente. Puede haber una buena razón por la que desea evitar el inicio de sesión de user_B, pero no ha dejado en claro por qué es preferible. Mi sugerencia evita el problema de esperar un tiempo de espera de la sesión para permitir el reinicio, a la vez que impide que el usuario inicie sesión dos veces. –

0

Usar el javascript del lado del cliente para rastrear usuarios no es confiable.

Puede obtener el mismo resultado simplemente creando un campo lastlogindate en la base de datos y actualizándolo con la última fecha de inicio de sesión de inicio de sesión del usuario.

En cada intento de inicio de sesión, si ahora() - $ lastlogindate> predefined_timeout, entonces debe aceptar el nuevo inicio de sesión, de lo contrario, rechazarlo.

1

Debe crear una ID única y almacenarla en una base de datos. Lo que hice fue crear también. Guardo uno en una variable de sesión y lo uso para evitar el secuestro de sesión y otro en una base de datos para evitar múltiples inicios de sesión. El siguiente código crea un identificador único:

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

Si la única identificación no coincide, sólo tiene que conectar al usuario a cabo.

4

Aquí es una solución que no requieren constante acceso a la base de datos a trabajar ...

(lo que evitará la necesidad de comprobar el session_id() con el valor de base de datos cada vez que se solicita/actualización una página, aliviando el estrés de db/server) ...

1.En de inicio de sesión, coge el session_id preexistente almacenada en la base de datos para este usuario y haga lo siguiente:

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

2. A continuación, iniciar una nueva sesión y guardar esta nueva session_id a la base de datos, sobrescribiendo el anterior . Esto cerrará la sesión anterior en este usuario si hay uno activo (efectivamente desconectando al otro tipo usando esta cuenta).

Pruébalo y avísame si eso funciona.

+0

Lo probé, funciona bien y sin estresar el servidor. Muy elegante - ¡Gracias! – cronoklee

+0

, pero ¿qué ocurre con la función session_regenerate_id()? porque lo he usado periódicamente? así que parece que tengo que guardar/actualizar la identificación regenerada en la base de datos también y por lo tanto hace el mismo estrés a db ¿verdad? –

Cuestiones relacionadas