jsp - que - ¿Cómo diferenciar sesiones en las pestañas del navegador?
tag jsp java (21)
En una aplicación web implementada en Java utilizando JSP y Servlets; si almaceno información en la sesión del usuario, esta información se comparte desde todas las pestañas del mismo navegador. ¿Cómo diferenciar sesiones en las pestañas del navegador? En este ejemplo:
<%@page language="java"%>
<%
String user = request.getParameter("user");
user = (user == null ? (String)session.getAttribute("SESSIONS_USER") : user);
session.setAttribute("SESSIONS_USER",user);
%>
<html><head></head><body>
<%=user %>
<form method="post">
User:<input name="user" value="">
<input type="submit" value="send">
</form>
</body></html>
Copie este código en una página jsp ( testpage.jsp
), implemente este archivo en un contexto existente de una aplicación web en el servidor (yo uso Apache Tomcat), luego abra un navegador (FF, IE7 u Opera) usando la URL correcta ( localhost/context1/testpage.jsp
), escriba su nombre en la entrada y envíe el formulario. Luego, abra una nueva pestaña en el mismo navegador y luego podrá ver su nombre (obtener de la sesión) en la nueva pestaña. Tenga cuidado con el caché del navegador, a veces parece que no sucede, pero está en el caché, actualice la segunda pestaña.
Gracias.
Almacenamiento de timeStamp en window.sessionStorage si aún no está configurado. Esto le dará un valor único para cada pestaña (incluso si las URL son las mismas)
http://www.javascriptkit.com/javatutors/domstorage.shtml
https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Storage
Espero que esto ayude.
Creo que lo que probablemente desee es mantener el estado de navegación en pestañas y no crear específicamente una sola sesión por pestaña. Esto es exactamente lo que el marco de Seam logra con su alcance / contexto de Conversación. Su implementación se basa en el hecho de que una identificación de conversación se propaga con cada solicitud y crea la noción de una conversación en el lado del servidor, que es algo que se encuentra entre una sesión y una solicitud. Permite el control del flujo de navegación y la gestión del estado.
Aunque está dirigido principalmente a JSF, eche un vistazo y compruebe si es algo de lo que puede sacar algunas ideas de: http://docs.jboss.org/seam/latest/reference/en-US/html_single/#d0e3620
Debe darse cuenta de que las sesiones del lado del servidor son un complemento artificial a HTTP. Como HTTP no tiene estado, el servidor debe reconocer de alguna manera que una solicitud pertenece a un usuario en particular que conoce y tiene una sesión. Hay 2 formas de hacer esto:
- Galletas. El método más limpio y popular, pero significa que todas las pestañas del navegador y las ventanas de un usuario comparten la sesión: IMO, de hecho, es deseable, y me molestaría mucho un sitio que me hizo iniciar sesión para cada pestaña nueva, ya que usa pestañas muy intensivamente
- Reescritura de URL. Cualquier URL en el sitio tiene una ID de sesión adjunta. Esto es más trabajo (tienes que hacer algo en todos lados donde tienes un enlace interno del sitio), pero hace posible tener sesiones separadas en diferentes pestañas, aunque las pestañas abiertas a través del enlace aún compartirán la sesión. También significa que el usuario siempre tiene que iniciar sesión cuando ingrese a su sitio.
¿Qué intentas hacer de todos modos? ¿Por qué querrías que las pestañas tuvieran sesiones separadas? Tal vez haya una manera de lograr su objetivo sin usar sesiones en absoluto?
Editar: para probar, se pueden encontrar otras soluciones (como ejecutar varias instancias de navegador en máquinas virtuales separadas). Si un usuario necesita actuar en diferentes roles al mismo tiempo, entonces el concepto de "rol" debe manejarse en la aplicación para que un inicio de sesión pueda tener varios roles. Tendrá que decidir si esto, usando la reescritura de URL o simplemente viviendo con la situación actual es más aceptable, porque simplemente no es posible manejar las pestañas del navegador por separado con sesiones basadas en cookies.
Desarrollé una solución a este problema recientemente usando Cookies. Aquí hay un enlace a mi solución. También incluí el código de muestra de la solución usando ASP.NET, usted debería poder adaptar esto a JSP o Servelets si lo necesita.
https://sites.google.com/site/sarittechworld/track-client-windows
He encontrado una nueva solución, que tiene un poco de sobrecarga, pero parece estar funcionando hasta ahora como un prototipo. Una suposición es que se encuentra en un entorno de sistema de honor para iniciar sesión, aunque esto podría adaptarse al volver a solicitar una contraseña cada vez que cambie de pestaña.
Use localStorage (o su equivalente) y el evento de almacenamiento HTML5 para detectar cuando una nueva pestaña del navegador ha cambiado qué usuario está activo. Cuando eso suceda, cree una superposición de fantasmas con un mensaje que diga que no puede usar la ventana actual (o deshabilite la ventana temporalmente). Cuando la ventana recupere el foco, envíe un registro de solicitud de AJAX. el usuario de nuevo en
Una advertencia a este enfoque: no puede tener ninguna llamada AJAX normal (es decir, las que dependen de su sesión) que suceden en una ventana que no tiene el foco (por ejemplo, si tiene una llamada que ocurre después de un retraso), a menos usted hace manualmente una llamada de reinicio de AJAX antes de eso. Entonces, realmente todo lo que necesita hacer es verificar primero su función AJAX para asegurarse de que localStorage.currently_logged_in_user_id === window.yourAppNameSpace.user_id, y si no, inicie sesión primero a través de AJAX.
Otra es las condiciones de carrera: si puede cambiar de ventana lo suficientemente rápido como para confundirlo, puede terminar con una secuencia relogin1-> relogin2-> ajax1-> ajax2, con ajax1 en la sesión incorrecta. Para solucionar este problema, haga clic en las solicitudes AJAX de inicio de sesión en una matriz y, a continuación, en el almacén y antes de emitir una nueva solicitud de inicio de sesión, cancele todas las solicitudes actuales.
Lo último que tuve que buscar fue la actualización de las ventanas. Si alguien actualiza la ventana mientras tiene una solicitud de inicio de sesión de AJAX activa pero no completada, se actualizará con el nombre de la persona incorrecta. En este caso, puede utilizar el evento de descarga previa no estándar para advertir al usuario sobre la confusión potencial y pedirle que haga clic en Cancelar, mientras vuelve a emitir una solicitud de inicio de sesión de AJAX. Entonces, la única forma en que pueden estropearlo es haciendo clic en Aceptar antes de que se complete la solicitud (o presionando accidentalmente la barra de espacio / entrada, porque OK es, por desgracia en este caso, el predeterminado). Hay otras maneras de manejar este caso, como detectar F5 y Ctrl + R / Alt + R presiona, lo que funcionará en la mayoría de los casos, pero podría verse frustrado por la reconfiguración del atajo de teclado del usuario o el uso alternativo del sistema operativo. Sin embargo, este es un caso marginal en la realidad, y los peores escenarios nunca son tan malos: en una configuración de sistema de honor, estarías conectado como la persona equivocada (pero puedes hacer obvio que este es el caso personalizando páginas con colores, estilos, nombres destacados, etc.); en una configuración de contraseña, la responsabilidad recae en la última persona que ingresó su contraseña para cerrar sesión o compartir su sesión, o si esta persona es realmente el usuario actual, entonces no hay infracción.
Pero al final tiene una aplicación de un usuario por ficha que (con suerte) simplemente actúa como debería, sin tener necesariamente que configurar perfiles, usar IE o reescribir URL. Sin embargo, asegúrese de hacerlo obvio en cada pestaña que está conectado a esa pestaña en particular ...
He estado leyendo esta publicación porque pensé que quería hacer lo mismo. Tengo una situación similar para una aplicación en la que estoy trabajando. Y realmente es una cuestión de probar más que practicidad.
Después de leer estas respuestas, especialmente la dada por Michael Borgwardt, me di cuenta del flujo de trabajo que debe existir:
- Si el usuario navega a la pantalla de inicio de sesión, verifica si hay una sesión existente. Si existe, omita la pantalla de inicio de sesión y envíela a la pantalla de bienvenida.
- Si el usuario (en mi caso) navega a la pantalla de inscripción, verifique una sesión existente. Si existe, deja que el usuario sepa que vas a iniciar sesión. Si aceptan, cierre la sesión y comience la inscripción.
Esto resolverá el problema de que los usuarios vean los datos de "otro usuario" en su sesión. En realidad, no ven los datos de "otro usuario" en su sesión, realmente están viendo los datos de la única sesión que tienen abierta. Claramente, esto causa algunos datos interesantes ya que algunas operaciones sobrescriben algunos datos de sesión y otros no, por lo que tiene una combinación de datos en esa única sesión.
Ahora, para abordar el problema de las pruebas. El único enfoque viable sería aprovechar las Directivas de preprocesador para determinar si se deben utilizar sesiones sin cookies. Ver, construyendo en una configuración específica para un entorno específico, puedo hacer algunas suposiciones sobre el entorno y para qué se utiliza. Esto me permitiría técnicamente tener dos usuarios conectados al mismo tiempo y el probador podría probar múltiples escenarios desde la misma sesión del navegador sin tener que desconectarse de ninguna de esas sesiones de servidor.
Sin embargo, este enfoque tiene algunas advertencias serias. No menos importante es el hecho de que lo que el probador está probando no es lo que se ejecutará en producción.
Así que creo que tengo que decir que, en última instancia, esta es una mala idea.
La propiedad window.name Javascript, es lo único que persistirá en la actividad de las pestañas, pero puede permanecer independiente (en lugar de guff URL).
Nota: la solución aquí debe hacerse en la etapa de diseño de la aplicación. Sería difícil diseñar esto más tarde.
Use un campo oculto para pasar el identificador de sesión .
Para que esto funcione, cada página debe incluir un formulario:
<form method="post" action="/handler">
<input type="hidden" name="sessionId" value="123456890123456890ABCDEF01" />
<input type="hidden" name="action" value="" />
</form>
Cada acción de su lado, incluida la navegación, envía el formulario POST (configurando la action
según corresponda). Para "unsafe" solicitudes "unsafe" , podría incluir otro parámetro, por ejemplo, que contenga un valor JSON de los datos que se enviarán:
<input type="hidden" name="action" value="completeCheckout" />
<input type="hidden" name="data" value=''{ "cardNumber" : "4111111111111111", ... '' />
Como no hay cookies, cada pestaña será independiente y no tendrá conocimiento de otras sesiones en el mismo navegador.
Muchas ventajas, particularmente cuando se trata de seguridad:
- Sin dependencia de JavaScript o HTML5.
- Inherentemente protege contra CSRF .
- No confiar en las cookies, por lo que protege contra POODLE .
- No es vulnerable a la fijación de la sesión .
- Puede evitar el uso del botón secundario, lo que es deseable cuando se desea que los usuarios sigan una ruta establecida a través de su sitio (lo que significa que pueden evitarse errores lógicos que a veces pueden ser atacados por solicitudes fuera de orden).
Algunas desventajas:
- Se puede desear la funcionalidad del botón Atrás.
- No es muy efectivo con el almacenamiento en caché ya que cada acción es un POST.
Más información aquí .
Otro enfoque que funciona es crear un ID de ventana único y almacenar este valor junto con el ID de sesión en una tabla de base de datos. La identificación de la ventana que uso a menudo es entera (ahora). Este valor se crea cuando se abre una ventana y se reasigna a la misma ventana si la ventana se actualiza, se recarga o se envía a sí misma. Los valores de ventana (entradas) se guardan en la tabla local usando el enlace. Cuando se requiere un valor, se obtiene de la tabla de la base de datos en función del enlace de la identificación de la ventana / id de la sesión. Si bien este enfoque requiere una base de datos local, es prácticamente infalible. El uso de una tabla de base de datos fue fácil para mí, pero no veo ninguna razón por la que las matrices locales no funcionen igual de bien.
Puede usar HTML5 SessionStorage (window.sessionStorage). Generará una identificación aleatoria y guardará en la sesión Almacenamiento por pestaña del navegador. Luego, cada pestaña del navegador tiene su propio Id.
Los datos almacenados con sessionStorage no persisten en las pestañas del navegador, incluso si dos pestañas contienen páginas web del mismo origen de dominio. En otras palabras, los datos dentro de sessionStorage están confinados no solo al dominio y directorio de la página de invocación, sino también a la pestaña del navegador en la que se encuentra la página. Contraste eso con las cookies de sesión, que persisten datos de pestaña a pestaña.
Puede usar la reescritura de enlaces para agregar un identificador único a todas sus URL al comenzar en una sola página (por ejemplo, index.html / jsp / whatever). El navegador usará las mismas cookies para todas sus pestañas, por lo que todo lo que ingrese en las cookies no será exclusivo.
Resolví esto de la siguiente manera:
- He asignado un nombre a la ventana Este nombre es el mismo del recurso de conexión.
- más 1 para deshacerse de las cookies almacenadas para conectarlas.
- Creé una función para capturar toda la respuesta xmloutput y asignar sid and rid a la cookie en formato json. Lo hago para cada window.name.
aquí el código:
var deferred = $q.defer(),
self = this,
onConnect = function(status){
if (status === Strophe.Status.CONNECTING) {
deferred.notify({status: ''connecting''});
} else if (status === Strophe.Status.CONNFAIL) {
self.connected = false;
deferred.notify({status: ''fail''});
} else if (status === Strophe.Status.DISCONNECTING) {
deferred.notify({status: ''disconnecting''});
} else if (status === Strophe.Status.DISCONNECTED) {
self.connected = false;
deferred.notify({status: ''disconnected''});
} else if (status === Strophe.Status.CONNECTED) {
self.connection.send($pres().tree());
self.connected = true;
deferred.resolve({status: ''connected''});
} else if (status === Strophe.Status.ATTACHED) {
deferred.resolve({status: ''attached''});
self.connected = true;
}
},
output = function(data){
if (self.connected){
var rid = $(data).attr(''rid''),
sid = $(data).attr(''sid''),
storage = {};
if (localStorageService.cookie.get(''day_bind'')){
storage = localStorageService.cookie.get(''day_bind'');
}else{
storage = {};
}
storage[$window.name] = sid + ''-'' + rid;
localStorageService.cookie.set(''day_bind'', angular.toJson(storage));
}
};
if ($window.name){
var storage = localStorageService.cookie.get(''day_bind''),
value = storage[$window.name].split(''-'')
sid = value[0],
rid = value[1];
self.connection = new Strophe.Connection(BoshService);
self.connection.xmlOutput = output;
self.connection.attach(''bosh@'' + BoshDomain + ''/'' + $window.name, sid, parseInt(rid, 10) + 1, onConnect);
}else{
$window.name = ''web_'' + (new Date()).getTime();
self.connection = new Strophe.Connection(BoshService);
self.connection.xmlOutput = output;
self.connection.connect(''bosh@'' + BoshDomain + ''/'' + $window.name, ''123456'', onConnect);
}
Espero ayudarte
Seré honesto aquí. . . todo lo anterior puede ser o no cierto, pero todo parece MUY complicado, o no trata de saber qué pestaña se está utilizando en el lado del servidor.
A veces tenemos que aplicar la navaja de Occam.
Aquí está el enfoque de Occam: (no, no soy Occam, murió en 1347)
1) asigna una identificación única del navegador a tu página en la carga. . . si y solo si la ventana aún no tiene una identificación (entonces use un prefijo y una detección)
2) en cada página que tenga (use un archivo global o algo similar) simplemente coloque el código en su lugar para detectar el evento de enfoque y / o el evento mouseover. (Usaré jquery para esta parte, para facilitar la escritura del código)
3) en su función de enfoque (y / o mouseover), configure una cookie con window.name en ella
4) lea ese valor de cookie desde el lado del servidor cuando necesite leer / escribir datos específicos de la pestaña.
Lado del cliente:
//Events
$(window).ready(function() {generateWindowID()});
$(window).focus(function() {setAppId()});
$(window).mouseover(function() {setAppId()});
function generateWindowID()
{
//first see if the name is already set, if not, set it.
if (se_appframe().name.indexOf("SEAppId") == -1){
"window.name = ''SEAppId'' + (new Date()).getTime()
}
setAppId()
}
function setAppId()
{
//generate the cookie
strCookie = ''seAppId='' + se_appframe().name + '';'';
strCookie += '' path=/'';
if (window.location.protocol.toLowerCase() == ''https:''){
strCookie += '' secure;'';
}
document.cookie = strCookie;
}
lado del servidor (C # - por ejemplo)
//variable name
string varname = "";
HttpCookie aCookie = Request.Cookies["seAppId"];
if(aCookie != null) {
varname = Request.Cookies["seAppId"].Value + "_";
}
varname += "_mySessionVariable";
//write session data
Session[varname] = "ABC123";
//readsession data
String myVariable = Session[varname];
Hecho.
Si se debe a que cada pestaña ejecutará un flujo diferente en su aplicación, y al mezclar ambos flujos ocasiona problemas, entonces es mejor "regionalizar" sus objetos de sesión, de modo que cada flujo use una región diferente de la sesión
Esta región puede implementarse simplemente con diferentes prefijos para cada flujo, o el objeto de sesión contendrá varios mapas (uno para cada flujo), y usted usará esos mapas en lugar de los atributos de la sesión, lo mejor sería ampliar su clase de sesión y Úselo en su lugar.
Spring Session admite múltiples sesiones en el mismo navegador. Mire las muestras y los detalles de implementación http://docs.spring.io/spring-session/docs/current/reference/html5/guides/users.html
Tuvimos este problema y lo resolvimos muy fácil. Quiero decir fácil porque no hay programación involucrada. Lo que queríamos hacer era permitir que un usuario iniciara sesión en varias cuentas dentro de la misma ventana del navegador sin entrar en conflicto con las sesiones.
Entonces la solución fue subdominios aleatorios.
23423.abc.com
242234.abc.com
235643.abc.com
Así que le pedimos a nuestro administrador del sistema que configure los certificados SSL para * .abc.com en lugar de abc.com Luego, con pocos cambios de código, cada vez que un usuario intenta iniciar sesión, se registra en una pestaña con un número de subdominio aleatorio. por lo que cada pestaña podría tener su propia sesión de forma independiente. También para evitar cualquier conflicto, desarrollamos el número aleatorio usando un hash o md5 de identificación de usuario.
Veo muchas implementaciones que tienen cambios en el lado del cliente para manipular cookies de id de sesión. Pero, en general, las cookies de identificación de sesión deben ser HttpOnly, por lo que java-script no puede acceder, de lo contrario, puede llevar a Session Hijack a través de XSS
deberás hacer
1- almacena una cookie para la lista de cuentas
2- Opcional almacenar una cookie por defecto
3- tienda para cada cuenta con su índice como acc1, acc2
4- poner en la url algo representar el índice de cuentas y si no seleccionará el predeterminado como google mail domain.com/0/some-url >> 0 aquí representa el índice de cuenta también es posible que necesite saber cómo usar urlwrite
5- Cuando seleccione una cookie, selecciónela según su urlpath represente el índice de la cuenta
Saludos
Esencialmente use window.name. Si no está configurado, configúrelo con un valor único y úselo. Será diferente en las pestañas que pertenecen a la misma sesión.
No deberias. Si desea hacer algo así, debe forzar al usuario a usar una sola instancia de su aplicación escribiendo URL sobre la marcha, utilice un Id. De sesión igual (no sessionid, no funcionará) y páselo en cada URL.
No sé por qué lo necesitas, pero a menos que necesites hacer una aplicación totalmente inutilizable, no lo hagas.
How to differ sessions in browser-tabs?
La forma más directa de diferir las sesiones en las pestañas del navegador es no permitir que su dominio particular establezca cookies. De esta forma, puede tener sesiones separadas de pestañas separadas. Supongamos que no permite las cookies de este dominio: www.xyz.com. Abre la pestaña 1, inicia sesión y comienza a navegar. Luego, abre la pestaña 2 y puede iniciar sesión como un mismo usuario o uno diferente; de cualquier manera, tendrá una sesión separada de la Pestaña 1. Y así sucesivamente.
Pero, por supuesto, esto es posible cuando tienes control sobre el lado del cliente. De lo contrario, las soluciones prescritas por la gente aquí deberían aplicarse.