¿Por qué los WAR no pueden compartir información de la sesión?

11

He visto a varios desarrolladores que buscan una solución para este problema: acceder a la información de sesión desde un WAR diferente (incluso dentro del mismo EAR). Aquí hay algunos ejemplos: ¿ Alguna forma de compartir el estado de sesión entre diferentes aplicaciones en Tomcat? , Sesión de acceso de otra aplicación web , diferentes archivos WAR, recursos compartidos , Tomcat: ¿Cómo compartir datos entre dos aplicaciones? , ¿Qué hace el atributo crossContext en Tomcat? ¿Permite compartir sesiones? y así...

De todo lo que he buscado, hay algunas soluciones específicas que dependen del contenedor, pero de alguna manera es ' contrario a la especificación '. También he examinado las especificaciones de Java EE sin suerte en encontrar una respuesta.

Algunos desarrolladores hablan sobre el acoplamiento entre aplicaciones web, pero tiendo a estar en desacuerdo. ¿Cuál es la razón por la que uno mantendría los WAR dentro del mismo EAR si no se acoplan? Se puede acceder a los EJB, por ejemplo, localmente (incluso dentro de otro JAR EJB dentro del mismo EAR).

Más específicamente, uno de mis WAR maneja la autenticación y la autorización, y me gustaría compartir esta información con otros WAR (en el mismo EAR). Me las arreglé para solucionar problemas similares antes empaquetando WAR como JAR y colocándolos en un proyecto WAR singular (WEB-INF / lib). Sin embargo, no me gusta esta solución (requiere un gran esfuerzo para nombrar servlets, etc.).

Y ninguna solución ha respondido a la primera (y más importante) pregunta: ¿por qué los WAR no pueden compartir información de la sesión?

rvcoutinho
fuente
1
No estoy seguro de por qué esto fue rechazado, aparte de que podría ser una mejor opción para SO.
NateDSaint
3
"De acuerdo con la especificación de la API del servlet 2.3, el administrador de sesión admite el alcance de la sesión solo por el módulo web. Solo los servlets en el mismo módulo web pueden acceder a los datos asociados con una sesión en particular". Esto se puede ver nuevamente en HttpSession : "La información de la sesión se limita a la aplicación web actual (ServletContext), por lo que la información almacenada en un contexto no será visible directamente en otro". - Hacerlo es contrario a la especificación.
(mejor, enlace actual para HttpSession )
@MichaelT, gracias. Pero todavía no responde por qué.
rvcoutinho
@NateDSaint Aunque la pregunta está relacionada con tecnologías específicas, creí que era más probable que fuera una pregunta conceptual. Entonces, me decidí por programadores.
rvcoutinho

Respuestas:

7

Tratar un EAR como una máquina pseudo-virtual.

Un EAR es simplemente una colección de archivos WAR que comparten una configuración y bibliotecas comunes, generalmente de JAR. Esto permite que una colección de servicios interdependientes se administre más fácilmente dentro de un contenedor de aplicaciones. Por lo tanto, puede pensar en un EAR como una forma simple de máquina virtual una vez que se implementa en su contenedor.

De la misma manera que un proceso en una máquina virtual no puede afectar a otro, lo mismo es cierto para un EAR. Todas las guerras están aisladas para proteger su estado interno.

Autenticación de escala

En general, las aplicaciones web deben ser apátridas para escalar bien. Tener mucha información en la sesión es un antipatrón que lo impide. Esto lleva a un conflicto entre la naturaleza sin estado de HTTP y la necesidad de mantener una experiencia de usuario rápida y personalizada. La autenticación es un caso de uso clásico, y prevalece en las API de conversación que requieren muchas solicitudes autenticadas para ofrecer la funcionalidad del usuario final.

El inicio de sesión único y el cierre de sesión único necesitan una señalización cuidadosa para funcionar correctamente (considere cerrar sesión parcialmente), particularmente cuando se aplica la escala horizontal. Simplemente compartir el estado de la sesión casi nunca es una buena solución y un mejor enfoque es utilizar un único punto de referencia para la información del usuario a la que tienen acceso todos los nodos del clúster.

Concentrarse en el acceso rápido en caché a la información relevante producirá resultados mucho más escalables que alguna solución compleja y frágil para compartir sesiones.

Gary Rowe
fuente
Gracias, @GaryRowe. Esta es la respuesta que estaba buscando. De todos modos, ¿no podría ser eso lo que decida el desarrollador?
rvcoutinho
Otra pregunta: ¿Crees que JBoss Cache podría ser una buena solución? ¿Has oído hablar de Apache Shiro (y su agrupación de sesiones)? ¿Qué hay de eso?
rvcoutinho
@rvcoutinho ¿El desarrollador de la aplicación decide cómo se gestionan los procesos en el kernel de Linux? Es una formulación similar de una pregunta: sí, podría hacerlo, pero será extremadamente difícil y probablemente le causará más dolor que tomar el camino alternativo.
Gary Rowe
2
@rvcoutinho No he usado Apache Shiro (también conocido como Apache Security) pero imagino que sería una buena solución para el problema de seguridad compartida. Definitivamente considere integrarse con OpenID y OAuth2 en lugar de implementar su propio protocolo para lograr lo mismo. JBoss Cache es por su propia admisión en un callejón sin salida que se reemplaza con Infinispan, que parece bastante complejo. Es posible que desee echar un vistazo al sitio de la aplicación Twelve-Factor para ver una solución más simple y escalable.
Gary Rowe
2

Creo que falta la funcionalidad de la especificación JEE EAR: la capacidad de compartir sesiones web en varios archivos web vinculados dentro de un EAR.

Los servidores de aplicaciones como Weblogic tienen implementaciones no estándar para esta funcionalidad.

Martijn Verburg
fuente
Esa fue mi opinión hasta ahora. Estaba tratando de entender por qué se hizo la elección mencionada.
rvcoutinho
1

Bueno, AFAIKS, no hay una razón real por la que te gustaría hacer esto. Un WAR es una aplicación web autónoma, con sus propios ámbitos (específicos de la aplicación web) (como el alcance de la sesión). Si necesita compartir funcionalidad (código Java, páginas JSP, archivos CSS), entre múltiples WAR tiene la opción mucho más sensata de empaquetarlos como archivos JAR e implementarlos en su servidor de aplicaciones. Un paquete WAR es una solución de empaque más compleja y está diseñada para encapsular algo diferente a un simple "código / funcionalidad común". El JAR es un formato más simple Y está diseñado para empaquetar y compartir código y funcionalidad. ¿Por qué desearía utilizar un paquete más complejo y no diseñado específicamente para ese producto para compartir algo, cuando ya tiene disponible un formato de paquete más simple y más adecuado para ese paquete?

Shivan Dragon
fuente
Estoy de acuerdo contigo. Pero solo cuando se trata solo de recursos generales. Pero, para una aplicación de inicio de sesión único, necesitaría compartir información específica de la sesión (sobre el usuario registrado). Y no veo ninguna razón por la cual esto estaría en contra de la especificación.
rvcoutinho
2
Debido a que el alcance de la sesión no está hecho para compartir datos de usuario actuales entre diferentes aplicaciones. Y porque SSO implica más que inspeccionar los atributos del alcance de la sesión. Puede crear y empaquetar código fuera de su guerra (y que no dependería de su guerra, sino que la guerra dependa de ella) que accedería a los atributos del alcance de la sesión si lo desea (como un filtro), pero la mejor solución en mi humilde opinión sería tener una configuración de servidor o aplicación de fachada separada que se ocupe de la autenticación y otorgue acceso a otras aplicaciones (desplegadas en guerra).
Shivan Dragon
De nuevo estaría de acuerdo contigo. Sin embargo, la especificación JavaEE (usando JAAS) contiene la información del usuario como parte de la HttpSession, que se opone a este enfoque. Una de las razones por las que he estado considerando usar Shiro (mantiene una sesión ortogonal).
rvcoutinho
De todos modos, gracias por la respuesta. Todavía no tengo una respuesta definitiva para mi pregunta, pero todo lo que ha dicho es relevante. +1
rvcoutinho
@rvcoutinho bueno, esa es mi opinión al respecto, lo siento, no fue más útil para usted.
Shivan Dragon
0

Creo que esto se hizo a propósito, para evitar que diferentes aplicaciones web sobrescriban accidentalmente la información de la sesión de los demás. Puede ser útil en su caso, pero en general, no desea que los usuarios bloqueen la aplicación o escalen sus privilegios solo porque usan dos aplicaciones web al mismo tiempo. No es exactamente difícil compartir explícitamente información entre aplicaciones web; simplemente cree una clase con un HashMap estático, use GUID como claves y transfiéralos como parte de la URL o el parámetro HTTP.

usuario281377
fuente
Gracias. En realidad, no estaba hablando de compartir toda la sesión entre cada aplicación, sino información específica de la sesión (como información del usuario) cuando era necesario. Quizás no estaba claro. ¿Alguna sugerencia para hacerlo más claro?
rvcoutinho