2008-11-18 20 views
16

En mi aplicación web, cuando un usuario inicia sesión, agrego su Id a un vector de Ids válidos en el servlet, cuando cierra la sesión, elimino su Id del vector, por lo que puedo ver cuántos usuarios actuales están activos , si un usuario se olvida de cerrar la sesión, mi servelt hTML generado tiene:¿Cómo detectar el cierre del navegador?

<meta http-equiv="Refresh" content="30; url=My_Servlet?User_Action=logout&User_Id=1111"> 

en la etiqueta para que ingrese a cabo de forma automática.

Pero he notado que muchos usuarios están ahí para siempre, nunca se han desconectado. Descubrí por qué, al cerrar sus navegadores, nunca se desconectaban de forma manual o automática, por lo que sus identificadores de usuario nunca se eliminarán del vector Ids de usuario válido.

Entonces, mi pregunta es: ¿cómo detecto a los usuarios que cierran sus navegadores, por lo que mi servlet puede eliminar sus Id del vector?


que ver algo de luz al final del túnel, pero todavía hay un problema, mi programa tiene algo como esto:

activa Lista de usuarios:

User_1 : Machine_1 [ IP_1 address ] 
User_2 : Machine_2 [ IP_2 address ] 
User_3 : Machine_3 [ IP_3 address ] 
... 

¿Cómo saber, del oyente de la sesión, qué sesión del usuario ha finalizado y, por lo tanto, eliminarlo de mi lista?

Esperaba que cuando la sesión termine, se llamaría al método destroy() del HttpServlet y puedo eliminar el Id del usuario allí, pero nunca se llama cuando el usuario cierra su navegador, ¿por qué? ¿Y hay algún otro método en el HttpServlet al que se llama cuando se cierra una sesión?

Respuesta

13

No hay forma de saber por el lado del servidor (a menos que esté utilizando JavaScript para enviar un mensaje al servidor) que el navegador ha cerrado. ¿Cómo podría haber? Piense en cómo funciona HTTP: todo es solicitud y respuesta.

Sin embargo, el servidor de aplicaciones rastreará cuándo las sesiones están activas e incluso le indicará cuándo se ha destruido una sesión (como debido a un tiempo de espera). Eche un vistazo al this page para ver cómo configurar un HttpSessionListener para recibir estos eventos. Luego, simplemente puede realizar un seguimiento de la cantidad de sesiones activas.

El número de sesiones activas se retrasará con respecto al número real de usuarios actuales, ya que debe transcurrir un período de tiempo (configurable) antes de que se agote el tiempo de espera de una sesión; sin embargo, esto debería ser algo cercano (puede reducir el tiempo de espera de la sesión para aumentar la precisión) y es mucho más limpio y fácil que 1) realizar el seguimiento de las sesiones usted mismo o 2) enviar un JavaScript asíncrono al servidor cuando se cierra un navegador (que no está garantizado para ser enviado).

+0

BTW - No tengo idea de cómo el código he vinculado a trabajará en un entorno agrupado/VM múltiples. Sospecho que no muy bien. –

+0

Este enlace http://www.stardeveloper.com/articles/display.html?article=2001112001&page=1 está roto. Actualiza tu respuesta – OO7

3

en JavaScript puede utilizar el evento onbeforeclose para devolver una llamada al servidor cuando el usuario cierra el navegador.

Normalmente uso una llamada síncrona Ajax para hacer esto.

+0

No, ver mi respuesta ... – PhiLho

7

Le sugiero que elimine la identificación cuando el motor Servlet destruye la sesión. Registre HttpSessionListener que elimina la identificación del usuario cuando se llama al sessionDestroyed().

La idea de Diodeus solo lo ayudará a detectar que la sesión finaliza de manera más inmediata.

2

No hay una manera infalible de hacer lo que está tratando de hacer, pero tanto el sblundy como Diodeus tienen planes que cubrirán la mayoría de las circunstancias. No hay nada que pueda hacer con alguien que desactive el Javascript en su navegador, o que su conexión a Internet se interrumpa, o que se apague. Deberías descartar las sesiones después de un cierto período de inactividad (que creo que es lo que hará la sugerencia de sblundy de escuchar la destrucción de la sesión).

2

Tuve que hacer eso recientemente, y después de algunas búsquedas, encontré algunas soluciones en la Red ... ¡todas ellas no funcionaban universalmente!

Los eventos onforeforeclose y onclose se usan para esta tarea. Pero hay dos capturas: se disparan cuando el usuario recarga la página o incluso simplemente cambia la página actual. Hay trucos para ver si el evento es en realidad un/página/pestaña de la ventana de cierre (mirando algunas propiedades DOM que van sin control en el evento de cierre), pero:

  • Ellos son el navegador depende
  • Los trucos son indocumentados, por lo tanto frágil
  • Y en realidad que varían a lo largo de la versión del navegador/actualización ...

Y lo peor de todo es que estos eventos están ahora ignorados por la mayoría de los navegadores modernos, ya que han sido objeto de abuso por los anuncios sin escrúpulos que hace estallar las ventanas cuando el navegador se estaba cerrando No se disparan en Safari, Opera, IE7, etc.

Como se señaló, la mayoría de las aplicaciones web con inicio de sesión destruyen la sesión del usuario después de un tiempo, por ej. media hora. Me pidieron que cerrara sesión en el cierre del navegador para liberar más rápido un recurso precioso: licencias. Debido a que los usuarios a menudo olvidan cerrar la sesión ...

La solución que proporcioné fue hacer ping con una solicitud Ajax (enviando la identificación del usuario) al servidor en intervalos regulares (digamos 1 minuto). Si el servidor no recibe ping durante, digamos, 3 minutos, desconecta al usuario.

+0

Esto es prácticamente lo mismo que usar un HttpSessionListener, excepto que usted tuvo que codificar el Ajax y el manejador del lado del servidor usted mismo, reinventando la rueda. –

+0

Estás bromeando, ¿verdad? HttpSessionListener es una interfaz, no proporciona Ajax ni magia. – PhiLho

0

Aquí hay una manera sucia de lograr "detectar un navegador cerrado" Lo encontré en un foro en algún lugar de este sitio, cuando lo encuentre de nuevo lo vincularé.

Agregue encabezados adicionales a la respuesta http. Cuando ingresen solicitudes adicionales, contendrán estos encabezados adicionales. Puede verificar estos encabezados y si no están presentes puede matar la sesión, por lo que se iniciará uno nuevo. Si bien esto no le "notifica" si el navegador está cerrado, puede decirle si alguien ha cerrado su ventana e intenta regresar, ya que los encabezados que agregó faltarán.

wrapper.setHeader("Cache-Control", "no-cache, no-store, must-  revalidate"); 
wrapper.setHeader("Pragma", "no-cache"); 
wrapper.setDateHeader("Expires", 0); 

Where wrapper is a response wrapper. 

if (wrapper.getHeaderNames().size() < the number of headers you are expecting) 
request.getSession().invalidate(); 

Not perfect but it might help someone. 
+0

Bueno, esto realmente no detecta un navegador cercano, solo detecta si alguien regresa a su servidor desde el mismo cliente, sin sus encabezados incluidos, por lo que los envía de regreso a su página de inicio de sesión. Entonces esta no es realmente una respuesta que valga la pena. – rjdamore

Cuestiones relacionadas