Java 同一ip但不同端口上的两台服务器之间的JSESSIONID冲突
我曾经遇到过这样一种情况:在一台服务器上运行两个不同的Web应用程序,使用不同的端口。他们都在运行Java的Jetty servlet容器,所以他们都使用一个名为JSESSIONID的cookie参数来跟踪会话id。这两个Web应用程序正在为会话id而争吵Java 同一ip但不同端口上的两台服务器之间的JSESSIONID冲突,java,http,cookies,jetty,Java,Http,Cookies,Jetty,我曾经遇到过这样一种情况:在一台服务器上运行两个不同的Web应用程序,使用不同的端口。他们都在运行Java的Jetty servlet容器,所以他们都使用一个名为JSESSIONID的cookie参数来跟踪会话id。这两个Web应用程序正在为会话id而争吵 打开Firefox选项卡,然后转到WebApp1 WebApp1的HTTP响应有一个设置cookie头,其JSESSIONID=1 Firefox现在在对WebApp1的所有HTTP请求中都有一个JSESSIONID=1的Cookie头 打
- 打开Firefox选项卡,然后转到WebApp1
- WebApp1的HTTP响应有一个设置cookie头,其JSESSIONID=1
- Firefox现在在对WebApp1的所有HTTP请求中都有一个JSESSIONID=1的Cookie头
- 打开第二个Firefox选项卡,然后转到WebApp2
- WebApp2的HTTP请求也有一个Cookie头,JSESSIONID=1,但在doGet中,当我调用
req.getSession(false)时代码>我得到
。如果我调用null
我会得到一个新的Session对象,但是来自WebApp2的HTTP响应有一个setcookie头,其JSESSIONID=20req.getSession(true)
- 现在,WebApp2有一个工作会话,但WebApp1的会话已不存在。转到WebApp1将给我一个新的会话,取消WebApp2的会话
- 永续
req.getSession(false)
返回一个有效的会话
一个选项是基本上用一个HashMap和一个叫做WEBAPP1SESSIONID和WEBAPP2SESSIONID的cookies重新实现会话框架,但这太糟糕了,这意味着我必须将新的会话内容破解到ActionServlet和其他一些地方
这一定是其他人遇到的问题。Jetty的
HttpServletRequest.getSession(布尔)
就是垃圾吗?这是正确的行为。您可以将两个Web应用程序放置到不同的域,或通过不同的路径。我相信您也可以设置jsessionid cookie路径。这不是Jetty的问题,而是cookie规范的定义方式。除了名称/值对之外,cookie还可能包含过期日期、路径、域名以及cookie是否安全(即仅用于SSL连接)。上面未列出端口号;-)因此,你需要改变路径或域,正如stepancheg在他的回答中所说 我一直在挖掘,发现在AbstractSessionManager
中有一个名为GetCrossContextSessionId()的方法。如果它返回true
,那么在创建新会话时,Jetty将首先检查是否设置了JSESSIONID,并尝试使用该现有会话id。我想我可以在启动时使用某种java属性将值设置为true
进一步挖掘,只有当我在同一个Jetty的不同上下文中运行两个webapp(因此,跨上下文)时,这才有助于我。创建新的会话
对象时,会选择一个新的JSESSIONID
值。如果getCrossContextSessionId()
返回true
,则它将检查当前的JSESSIONID
值是否由该Jetty(包括所有其他上下文)创建,如果是,它将重用它
由于我正在处理两个不同端口上运行的两个不同Jetty实例,我需要破解Jetty的源代码以不进行该检查,或者只是创建自己的类似于会话的框架。我遇到了一个类似的问题:本地主机上不同端口上的同一应用程序的一个或多个实例,在应用程序启动时选择,每个都使用自己的jetty实例
过了一会儿,我想到了这个:
- 等待jetty初始化
- 使用jetty的SocketManager获取端口(
SocketManager.getLocalPort()
)
- 通过SessionManager
(sessionHandler.getSessionManager().setSessionCookie(String)
)设置cookie名称
这样,每个实例的cookie名称就不同了,因此不再有干扰。在我们的例子中,我们使用的是Tomcat,所以解决方案是在每个实例上使用不同的会话cookie名称
在context.xml
中执行以下操作
<Context sessionCookieName="JSessionId_8080">
我的问题是,在Jetty创建新会话时,默认情况下,它甚至不尝试使用JSESSIONID的现有值。它只是为它选择了一个新的值。如果它重用现有的,那么我的两个Jetty实例就可以很好地发挥作用了。听起来你必须坚持使用Jetty——我不认为这个解决方案可以与其他servlet容器一起使用。希望你永远不需要切换:-)你是对的。我们正在考虑修改Jetty的代码作为短期修复。从长远来看,我们要么使用不同的cookie实现自己的会话管理,要么在实现SSO系统时一切都会改变。