Pregunta

Quiero evitar múltiples inicios de sesión en una aplicación PHP.

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

Cuando el usuario, un inicio de sesión en el estado del usuario se establecerá en 'Active', y si el usuario inicia sesión, el estado se establecerá en 'Notactive'. Cuando otro cliente se aplica a iniciar sesión con la misma cuenta de usuario, reviso la tabla de usuario. 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 del usuario puede actualizarse porque el usuario no hizo clic en el inicio de sesión.

¿Tiene alguna sugerencia sobre esto?

¿Fue útil?

Solución

(Tenga en cuenta que, si bien la técnica aquí sigue siendo algo válida; las muestras de PHP no deben copiarse a la altura, ya que hay medios más seguros para incorporar valores suministrados por el usuario en una consulta SQL)


En lugar de almacenar si el usuario está activo inactivo, es mejor almacenar algún atributo que se pueda verificar con el usuario por acción; Como en, cada vez que el usuario intenta hacer algo que requiera autenticación, verificará que este atributo coincida antes de que continúe.

Te recomiendo que hagas lo siguiente;

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

En segundo lugar, almacene este hash en su base de datos y en el usuario sesión En el momento del inicio de sesión. Hacerlo efectivamente 'iniciará sesión' al usuario anterior, ya que el hash debería ser diferente cada vez que alguien inicie sesión.

Dado que estamos utilizando sesiones, una cookie debe colocarse automáticamente en el navegador del usuario que contendrá una ID única que identifica al usuario a 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 llamará al comienzo de cada script para garantizar que el usuario esté autenticado. Este script debe consultar la base de datos, verificando si un usuario con la ID de su usuario tiene un hash que coincide 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;
    }
}

Entonces, simplemente pasamos authenticateUser() Los usuarios ID, hash (según los datos de su sesión) y un database link (Para una conexión de base de datos, deberá haber abierto antes).

Si authenticateUser() devoluciones true, el usuario está autenticado. Si false, el usuario no lo es o la base de datos no está disponible o hay un error 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 sabio hacer esto en proyectos gigantes donde miles de personas están iniciando sesión en un momento dado. Estoy seguro de que alguien puede sugerir mejoras.

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

Otros consejos

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

(que evitará el requisito de verificar la sesión_id () con el valor de la base de datos cada vez que solicite/actualice una página, aliviando el estrés de DB/servidor) ...

1. Al inicio de sesión, tome la sesión preexistente de session_id almacenada en el DB para este usuario y haga esto:

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

2. Luego comience una nueva sesión y guarde esta nueva sesión_id en la base de datos, sobrescribiendo la anterior. Esto iniciará sesión en la sesión anterior en este usuario si hay una activa (iniciar sesión efectivamente al otro tipo usando esta cuenta).

¡Pruébelo y avíseme si eso hace el truco!

Puede cambiar su modelo para que solo se pueda iniciar sesión al usuario más reciente.

Si registra la ID de sesión más reciente que se ve para cada usuario, cuando inicia sesión por segunda vez, puede basarse en cualquier sesión existente actualmente, logra efectivamente.

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

Lo que debe hacer es verificar si han estado activos en los últimos minutos al intentar iniciar sesión. Esto podría hacerse con un sello de LastOnline y debe configurarse en cada solicitud de página de la tabla de usuario.

Si no se hace con JavaScript, puede verificar, al iniciar sesión, si el usuario estaba 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 dispara 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 sello LastOnline en el DB del usuario. Al intentar iniciar sesión, verifica el DB del usuario si el sello LastOnline ha excedido el minuto y tiene su cheque si puede iniciar sesión. Esto ayudará cuando esté en la página, pero no está activo los últimos 15 minutos y no desea que alguien más inicie sesión.

Debe crear una identificación única y almacenarla en una base de datos. Lo que hice fue crear también. Almaceno 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 creará una identificación única:

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

Si la ID única no coincide, simplemente registra al usuario.

El uso del lado del cliente JavaScript para rastrear el usuario iniciado en el usuario no es confiable.

Puede obtener el mismo resultado simplemente creando un campo LastLogindate en el DB y actualizándolo con la última marca de tiempo 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.

Esta solución es similar a la de Prochahammer, pero no requiere que te metas con las sesiones de conmutación. No requiere que acceda a la base de datos en cada página y no bloquea al usuario después de que no cierre la sesión.

Agregue un campo para SessionID a su tabla de usuario en la base de datos.

Establezca el controlador de sesión predeterminado antes de llamar a session_start () (necesario para que funcione la siguiente línea de código):

session_set_save_handler(new \SessionHandler());

En cada inicio de sesión exitoso, recupere el $ sessionID almacenado de la base de datos. Destruye la vieja sesión con:

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

Obtenga la nueva ID de sesión con:

$sessionID = session_id();

Almacene la nueva ID de sesión en la base de datos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top