为什么WAR无法共享会话信息?


11

我已经看到一些开发人员在寻找解决此问题的方法:从不同的WAR(即使在同一EAR中)访问会话信息 -以下是一些示例:在tomcat中不同应用程序之间共享会话状态的任何方法?访问另一个Web应用程序的会话不同的WAR文件,共享资源Tomcat:如何在两个应用程序之间共享数据?crossContext属性在Tomcat中做什么?是否启用会话共享?等等...

从我搜索过的所有内容来看,有一些特定的解决方案取决于容器,但这在某种程度上“ 与规范相反 ”。我也浏览了Java EE规范,但没有找到答案的运气。

一些开发人员谈论Web应用程序之间的耦合,但是我倾向于不同意。如果不耦合,将WAR保留在同一个EAR中的原因是什么?例如,可以在本地访问EJB(即使在同一EAR中的另一个EJB JAR中也可以访问)。

更具体地说,我的一个WAR处理身份验证和授权,并且我想与其他WAR(在同一EAR中)共享此信息。在将WAR打包为JAR并将它们放入单个WAR项目(WEB-INF / lib)之前,我设法解决了类似的问题。但是我不喜欢这种解决方案(它需要在servlet命名上付出巨大的努力等等)。

而且没有解决方案可以回答第一个(也是最重要的)问题:为什么WAR无法共享会话信息?


1
不知道为什么不赞成这样做,除了可能更适合SO。
NateDSaint 2012年

3
“根据Servlet 2.3 API规范,会话管理器仅支持Web模块的会话作用域。只有同一Web模块中的Servlet才能访问与特定会话关联的数据。” 这可以在HttpSession中再次看到-“会话信息仅适用于当前Web应用程序(ServletContext),因此存储在一个上下文中的信息将不会在另一个上下文中直接可见。” -这样做违反规范。

(更好的,当前的HttpSession链接)

@MichaelT,谢谢。但是它仍然不能回答为什么。
rvcoutinho 2012年

@NateDSaint尽管该问题与特定技术有关,但我认为这更可能是一个概念性问题。然后,我决定选择程序员。
rvcoutinho 2012年

Answers:


7

像伪虚拟机一样对待EAR

EAR只是WAR文件的集合,这些文件共享通常来自JAR的通用配置和库。这使得相互依赖的服务的集合可以在应用程序容器中更容易地进行管理。因此,一旦将EAR部署到其容器中,便可以将其视为虚拟机的一种简单形式。

就像虚拟机上的一个进程无法影响另一个进程一样,EAR也是如此。所有WAR都是隔离的,以保护其内部状态。

扩展身份验证

通常,Web应用程序需要无状态才能很好地扩展。会话中包含大量信息是一种防止这种情况的反模式。这导致HTTP的无状态本质与保持快速的定制用户体验之间的冲突。身份验证是一种典型的用例,在需要大量经过身份验证的请求才能交付最终用户功能的健谈API中很普遍。

“单点登录”和“单点退出”需要谨慎的信号才能正常工作(考虑部分“签出”),尤其是在水平缩放时。仅仅共享会话状态几乎永远不是一个好的解决方案,更好的方法是对集群中所有节点均可访问的用户信息使用单一参考点。

与某些复杂,脆弱的会话共享解决方案相比,专注于快速缓存对相关信息的访问将产生可扩展性更高的结果。


谢谢,@ GaryRowe。这是我一直在寻找的答案。无论如何,这不是由开发商决定的吗?
rvcoutinho 2012年

另一个问题:您认为JBoss Cache可能是一个好的解决方案吗?您听说过Apache Shiro(及其会话集群)吗?那呢
rvcoutinho 2012年

@rvcoutinho应用程序开发人员是否确定如何在Linux内核中管理进程?这是一个类似的问题框架-是的,您可以做到,但是这将非常困难,并且可能会给您带来比选择替代方法更多的痛苦。
加里·罗维

2
@rvcoutinho我没有使用过Apache Shiro(又名Apache Security),但我想这将是解决共享安全问题的好方法。绝对考虑与OpenID和OAuth2集成,而不是滚动自己的协议来实现相同的目的。JBoss Cache自己承认,死胡同被Infinispan取代,后者看起来相当复杂。您可能想看一看十二因子应用程序站点,以了解更简单,更可扩展的解决方案。
加里·罗

2

我认为这是JEE EAR规范缺少的功能-跨EAR中绑定的多个Web归档共享Web会话的功能。

Weblogic之类的应用服务器具有此功能的非标准实现。


到目前为止,这是我的意见。我试图理解为什么做出上述选择。
rvcoutinho 2012年

1

好吧,AFAIKS,没有理由要这样做。WAR是一个自包含的Web应用程序,具有自己的(特定于Web应用程序的)作用域(如会话作用域)。如果需要在多个WAR之间共享功能(Java代码,JSP页面,CSS文件),则可以选择将它们打包为JAR文件并将其部署在应用程序服务器中的方法更为明智。WAR软件包是一种更为复杂的打包解决方案,它的设计目的是封装不同于简单的“通用代码/功能”的东西。JAR是一种更简单的格式,旨在包装和共享代码和功能。当您已经拥有一个更简单,更适合该包装格式的包装时,为什么要使用一个更复杂且不是专门针对该包装的包装来共享某些东西。


我同意你的看法。但仅在涉及一般资源时。但是,对于单个登录应用程序,我需要共享特定于会话的信息(关于登录用户)。而且我认为没有理由不符合规范。
rvcoutinho 2012年

2
因为没有将会话范围设为在不同应用程序之间共享当前用户数据。而且因为SSO所包含的意义不只是检查会话范围属性。您可以在战争之外(而不取决于战争,而取决于战争)制作和打包代码,这些代码可以在需要时访问会话范围属性(例如过滤器),但是更好的解决方案是IMHO拥有一个单独的外观应用程序或服务器配置来处理auth,并授予对其他(战争部署的)应用程序的访问权限。
Shivan Dragon

我会再次同意你的看法。但是,JavaEE规范(使用JAAS)将用户信息保留为HttpSession的一部分,这与该方法相反。我一直在考虑使用Shiro(保持正交会话)的原因之一。
rvcoutinho 2012年

无论如何,感谢您的答复。对于我的问题,我仍然没有确切的答案,但是您所说的一切都是相关的。+1
rvcoutinho 2012年

@rvcoutinho很好,这是我对此事的看法,对不起,这对您没有多大帮助。
Shivan Dragon

0

我认为这样做是有目的的,以避免不同的Web应用程序意外覆盖彼此的会话信息。在您的情况下,它可能会派上用场,但总的来说,您不希望用户仅仅因为他们同时使用两个Web应用程序而使应用程序崩溃或升级其特权。在Web应用程序之间显式共享信息并不是很难。只需使用静态HashMap创建一个类,使用GUID作为键并将它们作为URL或HTTP参数的一部分进行传输。


谢谢。实际上,我并不是在谈论在每个应用程序之间共享整个会话,而是在需要时共享特定的会话信息(作为用户信息)。也许我不清楚。有什么建议使其更清晰吗?
rvcoutinho 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.