2008-09-25 13 views
8

Hace unos años, desarrollé una aplicación web para la que queríamos asegurarnos de que los usuarios no compartieran las credenciales.¿Cómo me aseguro de que un usuario solo inicie sesión una vez?

Una de las cosas que decidimos hacer, solo permitía al usuario iniciar sesión desde una computadora a la vez. La forma en que hice esto, fue tener un pequeño iframe haciendo ping al servidor cada N segundos; siempre que el servidor tuviera un latido para un usuario en particular (desde una IP particular), ese usuario no tenía permiso para iniciar sesión desde ninguna otra IP.

La solución, a pesar de ser aprobada por mi gerente, siempre me pareció nociva. Además, parece que sería fácil eludirlo.

¿Hay alguna manera de asegurarse de que el usuario de una aplicación web solo inicie sesión una vez? Para ser sincero, nunca entendí por qué la gerencia incluso quería esta característica. ¿Tiene sentido hacer esto en aplicaciones distribuidas?

+0

¿alguna vez se encontró con problemas con el cambio de IP del cliente? o tu entorno estaba protegido de ese problema? – Owen

+0

No tuvimos problemas con el cambio de IP. Esta fue una aplicación para nuestros CSR para la cual controlamos las direcciones IP. –

Respuesta

11

Implementé esto al mantener una tabla hash de usuarios actualmente conectados, la clave era el nombre de usuario, el valor era su última actividad.

Al iniciar sesión, simplemente verifique esta tabla hash para la clave, y si existe, rechace el inicio de sesión.

Cuando el usuario hace algo, actualiza la tabla hash con el tiempo (Esto es fácil si la hace parte del marco de página principal).

Si el tiempo en la tabla hash es mayor a 20 minutos de inactividad, elimínelos. Puede hacer esto cada vez que se comprueba la tabla hash, por lo que incluso si solo tuviera un usuario e intentara iniciar sesión varias horas más tarde, durante esa comprobación inicial, los eliminaría de la tabla hash por estar inactivo.

Algunos ejemplos en C# (no probado):

public Dictionary<String,DateTime> UserDictionary 
{ 
    get 
    { 
     if (HttpContext.Current.Cache["UserDictionary"] != null) 
     { 
      return HttpContext.Current.Cache["UserDictionary"] as Dictionary<String,DateTime>; 
     } 
     return new Dictionary<String,DateTime>(); 
    } 
    set 
    { 
     HttpContext.Current.Cache["UserDictionary"] = value; 
    } 
} 

public bool IsUserAlreadyLoggedIn(string userName) 
{ 
    removeIdleUsers(); 
    return UserDictionary.ContainsKey(userName); 
} 

public void UpdateUser(string userName) 
{ 
    UserDictionary[userName] = DateTime.Now; 

    removeIdleUsers(); 
} 

private void removeIdleUsers() 
{ 
    for (int i = 0; i < UserDictionary.Length; i++) 
     { 
      if (user[i].Value < DateTime.Now.AddMinutes(-20)) 
       user.RemoveAt(i); 
     } 
} 
+0

¿Por qué se bajó este voto? Es la única forma sensata de hacerlo. – FlySwat

+0

No tengo idea. Voto ascendente. – ceejayoz

+0

Me gusta su solución. De hecho, la inactividad (y saber cuándo dejar que el usuario regrese), fue una de las cosas que me causó más problemas. Me gusta la idea de hacer que el control de "actividad del usuario" sea parte de la funcionalidad básica de cada página. –

1

En una aplicación de alta seguridad, se le puede solicitar que lo haga. Lo que puede hacer es mantener un recuento de inicio de sesión incrementándolo para el usuario que inicia sesión y la dirección IP. El recuento nunca debe ser 2. Si es así, usted registra la otra IP y cualquiera que esté conectado a esa IP se descarta. Eso no evitará que el usuario-1 le de sus credenciales al usuario-2, sino que hará que sea frustrante para el usuario-1 hacer su trabajo si el usuario-2 inicia sesión en otro lugar al mismo tiempo.

1

Nunca he encontrado una solución estándar para este problema. En una de mis aplicaciones utilicé una combinación de JavaScript + Java para garantizar que un usuario pudiera registrarse solo una vez desde una IP específica (en realidad era una ID de sesión), pero en el peor de los casos, por un tiempo de espera (establecido en 2 minutos) la cuenta no estaba disponible. No sé por qué no hay una forma común de hacerlo.

3

Mirar apenas IP pueden ser poco fiables. IIRC hay algunos estilos de proxy que generan solicitudes de salida aleatoriamente sobre múltiples direcciones IP. Dependiendo del alcance de su aplicación, esto puede afectarlo o no. Otros proxies mostrarán montones de tráfico desde una única IP.

El último tiempo de inicio de sesión también puede ser un problema. Considere la autenticación basada en cookies donde las cookies de autenticación no son persistentes (algo bueno). Si el navegador se bloquea o se cierra, el usuario debe volver a iniciar sesión, pero no puede hasta que expire el tiempo de espera. Si la aplicación es para negociar acciones, 20 minutos de no trabajo cuesta dinero y es probablemente inaceptable.

Por lo general, se pueden comprar cortafuegos/enrutadores inteligentes que hacen un mejor trabajo del que usted o yo podemos hacer como una sola vez.También ayudan a prevenir ataques de repetición, robo de cookies, etc., y se pueden configurar para que se ejecuten junto con los mecanismos estándar en su plataforma web de su elección.

1

Acabo de tener este problema.

Estábamos construyendo un sitio de Drupal que contenía una aplicación Flex (construido por el cliente), y quería lo siguiente:

  1. de acceso transparente desde Drupal < -> Flex (! Bleh)
  2. sin ¡inicios de sesión concurrentes!

puso a prueba a la mierda de todas las soluciones, y al final, esto es lo que hicimos:

  • Pasamos a lo largo del ID de sesión a través de cada URL.
  • Cuando el usuario inició sesión, establecimos una huella de fecha y hora-IP-SessionID-Nombre de usuario
  • Cada página, se hacía ping al DB, y si el mismo usuario se encontraba en la misma IP con un SessionID diferente, mayores de usuario se inicia

Estas soluciones satisfacen la prueba rigurosa de nuestro cliente (2 ordenadores en su house..he nos mantenían despiertos durante horas encontrar pequeños rincones y grietas en el código antes de venir a esta solución)

4

Daría la vuelta al problema y permitiría el último inicio de sesión a expensas de cualquier inicio de sesión anterior, de modo que cada vez que un usuario inicie sesión, finalice cualquier otro Es posible que tenga sesiones de inicio de sesión.

Esto es mucho más fácil de implementar, y terminas sabiendo dónde estás.

4

Después de haber trabajado en una 'función' como esta, advirtió: esta es una trampa de elefantes en casos extremos donde termina pensando que la tiene clavada y luego usted o alguien más dice "¿y si alguien hizo X?" y te das cuenta de que tienes que agregar otra capa de complejidad.

Por ejemplo:

  • lo que si un usuario abre una nueva pestaña con una copia de la sesión?
  • ¿Qué sucede si el usuario abre una nueva ventana del navegador?
  • ¿Qué sucede si el usuario inicia sesión y su navegador se bloquea?

y así sucesivamente ...

Básicamente hay una gama de soluciones más o menos hacky ninguno de los cuales son a toda prueba y todos los cuales van a ser difíciles de mantener. Por lo general, el objetivo real del cliente es otro objetivo de seguridad legítimo, como 'detener a los usuarios que comparten cuentas'.

La mejor idea es descubrir cuál es el objetivo subyacente y encontrar la forma de cumplirlo. Y me temo que eso implica diplomacia de negociación y otras "habilidades blandas" en lugar de embarcarse en una técnica de búsqueda inútil ...,

Cuestiones relacionadas