在 Tomcat 中的上下文之间共享会话数据

Posted

技术标签:

【中文标题】在 Tomcat 中的上下文之间共享会话数据【英文标题】:Sharing session data between contexts in Tomcat 【发布时间】:2012-03-15 06:09:21 【问题描述】:

我一直在寻找在多个战争文件之间共享会话数据的解决方案。我遇到了以下解决方案http://www.fwd.at/tomcat/sharing-session-data-howto.html

它的基本思想是,如果你有多个war文件,你可以使用第一个上下文的sessionid设置一个cookie。

可以使用适用于所有上下文/应用程序的路径设置 cookie。

例如,如果我有 3 个应用程序的以下配置

/myapp/app1
/myapp/app2
/myapp/app3

我可以如下设置一个cookie

/myapp 会话标识。

然后,sessionid cookie 将被发送到地址中包含 /myapp 的任何请求。这允许会话 ID 被任何上下文使用。

这种方法的唯一问题是它是在 2003 年编写并在 Tomcat 4 上测试的。

您对这种方法有何看法?有没有更好的方法?

谢谢

【问题讨论】:

【参考方案1】:

据我所知,没有直接的方法可以做到这一点,但是如果这些上下文共享同一个域,您可以使用域级别的 cookie。

您可以将数据放入 cookie 中(我不建议这样做)。

或者放置一个安全的会话 ID,您可以使用它来访问某种形式的存储(数据库或分布式缓存等)以检索您需要的数据。

【讨论】:

我忘了说,上下文都在同一个 Tomcat 实例中运行。 我不认为这有什么区别,但我很可能是错的。 我猜的另一个选项是将cookie路径设置为“/” 这就是我将其设置为域的意思。我认为这是这里唯一的选择。【参考方案2】:

如果数据量不是天文数字并且数据本身变化不是太快,您可能需要考虑使用 JNDI。此解决方案专为您的需求而设计。

您可以查看official documentation 或this post to tomcat-user mailing list 以获取参考和示例。

【讨论】:

你能给我举个例子来说明如何实现这一点。谢谢【参考方案3】:

那篇文章确实过时了。

在 Tomcat 5.5 和 6.0 上,您只需在 /conf/server.xml<Connector> 元素中将 emptySessionPath 属性设置为 true

<Connector ... emptySessionPath="true">

在 Tomcat 7.0 上,这已经改变,因为现在可以从 Servlet 3.0 API 配置。然后在 Tomcat 一侧,可通过在任何负责的 context.xml 文件中的 &lt;Context&gt; 元素中将 sessionCookiePath 设置为 / 进行配置。

<Context ... sessionCookiePath="/">

如前所述,有一个新的 Servlet 3.0 API 允许您通过标准 API 配置会话 cookie。您可以通过将以下内容添加到web.xml 以声明方式执行此操作:

<session-config>
    <cookie-config>
        <path>/</path>
    </cookie-config>
</session-config>

或通过SessionCookieConfig 以编程方式通过ServletContext#getSessionCookieConfig() 提供。

getServletContext().getSessionCookieConfig().setPath("/");

您可以在ServletContextListener#contextInitialized()HttpServlet#init() 中执行此操作。

另见:

Tomcat 5.5 HTTP connector documentation Tomcat 6.0 HTTP connector documentation - 提到潜在的安全漏洞 Tomcat 7.0 context documentation

【讨论】:

这是非常有用的信息。我不太明白其中大部分是如何工作的,但至少它给了我一个指向进一步调查的地点和内容的指针。是否有任何使用这些方法的示例?我正在使用 Tomcat 6.0 /conf/server.xml 在 Tomcat 的安装文件夹中。只需在 text/xml 编辑器中打开 XML 文件,找到用于为您的 web 应用程序提供服务的 &lt;Connector&gt; 元素,并将 emptySessionPath="true" 属性添加到该元素。 如果我将 emptySessionPath 设置为 true,是否所有应用程序都获得相同的 jsessionid 还是仍然获得不同的 jsessionid?谢谢 web.xml 上设置 cookie 路径也适用于 Glassfish,确实 在 Tomcat 9 (***.com/q/40753753/274677) 中,web.xml 中的 元素似乎被忽略了。重要的是属性sessionCookiePath 在tomcat 范围内的context.xml(在/conf 中)或特定于WAR 的context.xmlMETA-INF 中的值。您能否澄清您的答案是否需要同时设置 context.xmlweb.xml 或者是否需要设置,优先级是什么?根据我的经验,只使用了context.xml。这里也没有提到web.xml:tomcat.apache.org/tomcat-7.0-doc/config/context.html【参考方案4】:

对于 Tomcat 8,我使用以下配置在 2 个 web 应用程序之间共享会话:

conf/context.xml

<Context sessionCookiePath="/">

    <Valve className="org.apache.catalina.valves.PersistentValve"/>
    <Manager className="org.apache.catalina.session.PersistentManager">
        <Store className="org.apache.catalina.session.FileStore" directory="$catalina.base/temp/sessions"/>
    </Manager>

    ...

</Context>

我两次部署相同的简单 webapp log.warlog2.war

/log
/log2

我现在可以登录/log 并在/log2 中显示用户,这不适用于tomcat 默认配置。

设置并读取会话值:

HttpSession session=request.getSession();  
session.setAttribute("name",name);

HttpSession session=request.getSession(false);  
String name=(String)session.getAttribute("name");  

我以这个项目为例:https://www.javatpoint.com/servlet-http-session-login-and-logout-example

大多数示例/解决方案使用需要更多设置工作的内存数据库:

redis hazelcast

【讨论】:

以上是关于在 Tomcat 中的上下文之间共享会话数据的主要内容,如果未能解决你的问题,请参考以下文章

有啥方法可以在tomcat中的不同应用程序之间共享会话状态?

当每个线程可以处理与其他线程中的数据无关的数据时,是不是可以在线程之间重用一个共享托管对象上下文?

在核心数据的上下文之间共享非持久对象?

我可以在同一Camel上下文中的Camel Routes之间共享本地数据吗?

在 Django 中的视图之间共享上下文?

Flask基础之上下文