javascript - salir - ¿Cómo detectar el cierre del navegador?
jquery al salir de la pagina (6)
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 olvida cerrar la sesión, mi html generado por servelt tiene:
<meta http-equiv="Refresh" content="30; url=My_Servlet?User_Action=logout&User_Id=1111">
en la etiqueta para desconectarlo automáticamente
Pero me he dado cuenta de que muchos usuarios están ahí para siempre, nunca se desconectaron. 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, entonces mi servlet puede eliminar sus Id del vector?
Veo algo de luz al final del túnel, pero todavía hay un problema, mi programa tiene algo como esto:
Lista de usuarios activos:
User_1 : Machine_1 [ IP_1 address ]
User_2 : Machine_2 [ IP_2 address ]
User_3 : Machine_3 [ IP_3 address ]
...
¿Cómo puedo saber, por parte del oyente de la sesión, qué sesión del usuario ha finalizado y, por lo tanto, eliminarlo de mi lista?
Esperaba que, cuando finalizara la sesión, se llamara al método destroy()
del HttpServlet y pudiera eliminar el ID del usuario, 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?
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 se 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á cuando las Sesiones estén activas e incluso le indicará cuándo se ha destruido una Sesión (como por ejemplo debido al tiempo de espera). Eche un vistazo a esta página 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).
No hay una forma infalible de hacer lo que estás tratando de hacer, pero tanto él 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).
Tuve que hacer eso recientemente, y después de algunas búsquedas, encontré algunas soluciones en la red ... ¡todas ellas no funcionan 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 cierre de ventana / página / pestaña (viendo algunas propiedades de Dom que se vuelven locas en el evento de cierre), pero:
- Ellos dependen del navegador
- Los trucos son indocumentados, por lo tanto frágiles
- Y en realidad varían a lo largo de la versión / actualización del navegador ...
Y, lo peor de todo, estos eventos ahora son ignorados por la mayoría de los navegadores modernos, ya que han sido abusados por los anuncios falsos que salían de 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 ejemplo. media hora. Me pidieron que cerrara sesión en el cierre del navegador para liberar más rápido un recurso precioso: licencias. Porque los usuarios a menudo olvidan cerrar la sesión ...
La solución que di fue hacer ping con una solicitud de Ajax (enviando la ID de usuario) al servidor en intervalos regulares (digamos 1 minuto). Si el servidor no recibe ping durante, digamos, 3 minutos, desconecta al usuario.
en JavaScript puede usar el evento onbeforeclose
para pasar una llamada al servidor cuando el usuario cierra el navegador.
Normalmente utilizo una llamada síncrona Ajax para hacer esto.
Aquí hay una manera sucia de lograr "detectar un navegador cercano" Encontré esto 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.
Te sugiero que elimines la identificación cuando el motor Servlet destruye la sesión. Registre un HttpSessionListener
que elimine la identificación del usuario cuando se sessionDestroyed()
.
La idea de Diodeus solo te ayudará a detectar que la sesión finaliza de manera más inmediata.