Por que os WARs não podem compartilhar informações da sessão?


11

Vi vários desenvolvedores procurando uma solução para esse problema: acessando informações da sessão de um WAR diferente (mesmo quando dentro do mesmo EAR) - aqui estão alguns exemplos: Alguma maneira de compartilhar o estado da sessão entre aplicativos diferentes no tomcat? , Sessão de acesso de outro aplicativo da web , arquivos WAR diferentes, recursos compartilhados , Tomcat: Como compartilhar dados entre dois aplicativos? , O que o atributo crossContext faz no Tomcat? Ele permite o compartilhamento de sessões? e assim por diante...

De tudo que procurei, existem algumas soluções específicas, dependendo do contêiner, mas é de alguma forma ' contrário à especificação '. Também examinei a especificação Java EE sem nenhuma sorte em encontrar uma resposta.

Alguns desenvolvedores falam sobre o acoplamento entre aplicativos da Web, mas eu discordo. Qual é o motivo pelo qual os WARs manteriam o WAR dentro do mesmo EAR, se não estiverem acoplados? Os EJBs, por exemplo, podem ser acessados ​​localmente (mesmo que dentro de outro EJB JAR dentro do mesmo EAR).

Mais especificamente, um dos meus WARs lida com autenticação e autorização, e eu gostaria de compartilhar essas informações com outros WARs (no mesmo EAR). Eu já consegui solucionar problemas semelhantes antes, empacotando WARs como JARs e colocando-os em um projeto WAR único (WEB-INF / lib). No entanto, eu não gosto dessa solução (ela requer um grande esforço na nomeação de servlets e assim por diante).

E nenhuma solução respondeu à primeira (e mais importante) pergunta: Por que os WARs não podem compartilhar informações da sessão?


1
Não sei por que isso foi prejudicado, além de poder ser um ajuste melhor para o SO.
NodeDSaint

3
"De acordo com a especificação da API do servlet 2.3, o gerenciador de sessões suporta o escopo da sessão apenas pelo módulo da Web. Somente servlets no mesmo módulo da Web podem acessar os dados associados a uma sessão específica." Isso pode ser visto novamente no HttpSession - "As informações da sessão são definidas apenas para o aplicativo da Web atual (ServletContext), portanto, as informações armazenadas em um contexto não serão diretamente visíveis em outro". - Fazer isso é contrário à especificação.

(link melhor e atual para HttpSession )

@ MichaelT, obrigado. Mas ainda não responde o porquê.
rvcoutinho 04/12/12

@NateDSaint Embora a pergunta esteja relacionada a tecnologias específicas, eu acreditava que era mais provável que fosse uma pergunta conceitual. Então, eu decidi para programadores.
rvcoutinho 5/12/12

Respostas:


7

Trate um EAR como uma máquina pseudo-virtual

Um EAR é simplesmente uma coleção de arquivos WAR que compartilham configurações e bibliotecas comuns, geralmente de JARs. Isso permite que uma coleção de serviços interdependentes seja gerenciada mais facilmente em um contêiner de aplicativo. Assim, você pode pensar em um EAR como uma forma simples de máquina virtual, uma vez que é implantada em seu contêiner.

Da mesma maneira que um processo em uma máquina virtual não pode afetar outro, o mesmo se aplica a um EAR. Todos os WARs são isolados para proteger seu estado interno.

Escalando autenticação

Em geral, os aplicativos da web precisam ser sem estado para dimensionar bem. Ter muitas informações na sessão é um antipadrão que impede isso. Isso leva a um conflito entre a natureza apátrida do HTTP e a necessidade de manter uma experiência rápida e personalizada do usuário. A autenticação é um caso de uso clássico e prevalece nas APIs de bate-papo que exigem muitas solicitações autenticadas para fornecer funcionalidade ao usuário final.

O Logon único e o Logoff único precisam de uma sinalização cuidadosa para funcionar corretamente (considere o Logoff parcial), principalmente quando a escala horizontal está em vigor. Simplesmente compartilhar o estado da sessão quase nunca é uma boa solução e uma abordagem melhor é usar um único ponto de referência para as informações do usuário às quais todos os nós no cluster têm acesso.

A concentração no acesso rápido e em cache às informações relevantes produzirá resultados muito mais escaláveis ​​do que alguma solução complexa e frágil de compartilhamento de sessões.


Obrigado, @ GaryRowe. Esta é a resposta que eu estava procurando. Enfim, não poderia ser que o desenvolvedor decidisse?
rvcoutinho 5/12/12

Outra pergunta: Você acha que o JBoss Cache pode ser uma boa solução? Você já ouviu falar do Apache Shiro (e seu cluster de sessões)? Que tal isso?
rvcoutinho 5/12/12

@rvcoutinho O desenvolvedor do aplicativo decide como os processos são gerenciados no kernel do Linux? É uma estrutura semelhante a uma pergunta - sim, você poderia fazer isso, mas será extremamente difícil e provavelmente causará mais dor do que seguir o caminho alternativo.
Gary Rowe

2
@rvcoutinho Não usei o Apache Shiro (também conhecido como Apache Security), mas imagino que seria uma boa solução para o problema de segurança compartilhada. Definitivamente, considere a integração com o OpenID e o OAuth2, em vez de lançar seu próprio protocolo para obter a mesma coisa. O JBoss Cache é, por sua própria admissão, em um beco sem saída, sendo substituído pelo Infinispan, que parece bastante complexo. Você pode dar uma olhada no site do Twelve-Factor App para ter uma idéia de uma solução mais simples e escalável.
Gary Rowe

2

Acho que falta alguma funcionalidade na especificação JEE EAR - a capacidade de compartilhar sessões da web entre vários arquivos da web vinculados a um EAR.

Servidores de aplicativos como o Weblogic têm implementações não padrão para essa funcionalidade.


Essa foi a minha opinião até agora. Eu estava tentando entender por que a escolha mencionada foi feita.
Rvcoutinho

1

Bem, AFAIKS, não há nenhuma razão real para você querer fazer isso. Um WAR é um aplicativo da web independente, com escopos próprios (específicos do aplicativo da web) (como o escopo da sessão). Se você precisar compartilhar a funcionalidade (código Java, páginas JSP, arquivos CSS), entre vários WARs, você terá a opção muito mais sensata de empacotá-los como arquivos JAR e implementá-los em seu servidor de aplicativos. Um pacote WAR é uma solução de empacotamento mais complexa e projetada para encapsular algo diferente do simples "código / funcionalidade comum". O JAR é um formato mais simples e foi projetado para empacotar e compartilhar código e funcionalidade. Por que você deseja usar um pacote mais complexo e não especificamente projetado para esse compartilhamento para compartilhar algo, quando você já possui um formato de pacote mais simples e mais adequado a esse pacote?


Eu concordo com você. Mas somente quando se trata apenas de recursos gerais. Mas, para um aplicativo de logon único, eu precisaria compartilhar informações específicas da sessão (sobre o usuário conectado). E não vejo razão para que isso seja contrário às especificações.
rvcoutinho 4/12/12

2
Como o escopo da sessão não foi criado para compartilhar dados atuais do usuário entre aplicativos diferentes. E porque o SSO implica mais do que inspecionar os atributos do escopo da sessão. Você pode criar e empacotar código fora de sua guerra (e que não dependeria de sua guerra, mas a guerra dependeria dela) que acessaria os atributos do escopo da sessão se você quisesse (como um filtro), mas a melhor solução IMHO seria ter um aplicativo de fachada separado ou uma configuração de servidor que lide com a autenticação e conceda acesso a outros aplicativos (implementados em guerra).
Shivan Dragon

Eu voltaria a concordar com você. No entanto, a especificação JavaEE (usando JAAS) mantém as informações do usuário como parte do HttpSession, que se opõe a essa abordagem. Uma das razões pelas quais eu considerei usar o Shiro (ele mantém uma sessão ortogonal).
rvcoutinho 5/12/12

De qualquer forma, obrigado pela resposta. Ainda não tenho uma resposta definitiva para minha pergunta, mas tudo o que você disse é relevante. +1
rvcoutinho

@rvcoutinho bem, essa é a minha opinião sobre o assunto, desculpe, não foi mais útil para você.
Shivan Dragon

0

Acho que isso foi feito de propósito, para evitar que diferentes aplicativos da Web substituam acidentalmente as informações da sessão uns dos outros. Pode ser útil no seu caso, mas, em geral, você não deseja que os usuários causem falha no aplicativo ou aumentem seus privilégios apenas porque eles usam dois aplicativos da Web ao mesmo tempo. Não é exatamente difícil compartilhar informações explicitamente entre aplicativos da Web; basta criar uma classe com um HashMap estático, usar GUIDs como chaves e transferi-las como parte do parâmetro URL ou HTTP.


Obrigado. Na verdade, eu não estava falando em compartilhar a sessão inteira entre todos os aplicativos, mas em informações específicas da sessão (como informações do usuário) quando necessário. Talvez eu não tenha sido claro. Alguma sugestão sobre como torná-lo mais claro?
Rvcoutinho 5/12/12
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.