JSESSIONID collision between two servers on same i

2020-02-28 04:13发布

I've got a situation where I have two different webapps running on a single server, using different ports. They're both running Java's Jetty servlet container, so they both use a cookie parameter named JSESSIONID to track the session id. These two webapps are fighting over the session id.

  • Open a Firefox tab, and go to WebApp1
  • WebApp1's HTTP response has a set-cookie header with JSESSIONID=1
  • Firefox now has a Cookie header with JSESSIONID=1 in all it's HTTP requests to WebApp1
  • Open a second Firefox tab, and go to WebApp2
  • The HTTP reqeust to WebApp2 also has a Cookie header with JSESSIONID=1, but in the doGet, when I call req.getSession(false); I get null. And if I call req.getSession(true) I get a new Session object, but then the HTTP response from WebApp2 has a set-cookie header with JSESSIONID=20
  • Now, WebApp2 has a working Session, but WebApp1's session is gone. Going to WebApp1 will give me a new session, blowing away WebApp2's session.
  • Continue forever

So the Sessions are thrashing between each web app. I'd really like for the req.getSession(false) to return a valid session if there's already a JSESSIONID cookie defined.

One option is to basically reimplement the Session framework with a HashMap and cookies called WEBAPP1SESSIONID and WEBAPP2SESSIONID, but that sucks, and means I'll have to hack the new Session stuff into ActionServlet and a few other places.

This must be a problem others have encountered. Is Jetty's HttpServletRequest.getSession(boolean) just crappy?

6条回答
Lonely孤独者°
2楼-- · 2020-02-28 04:28

It is correct behavior. You can place two your webapps to different domains, or by different paths.

查看更多
虎瘦雄心在
3楼-- · 2020-02-28 04:31

It's not Jetty's problem, it's how the cookie specification was defined. Beside the name/value pair, a cookie may also contain an expiration date, a path, a domain name, and whether the cookie is secure (i.e. intended only for SSL connections). The port number is not listed in the above ;-) so you'll need to vary either the path or the domain, as stepancheg says in his answer.

查看更多
Emotional °昔
4楼-- · 2020-02-28 04:31

I've been digging, and I found that in AbstractSessionManager, there's a method called getCrossContextSessionIDs(). If it returns true, then when creating a new session, Jetty will first check if JSESSIONID is set, and try to use that existing session id. I think I can set the values to true using some kind of java property on startup.

On further digging, this will only help me if I'm running two webapps in different contexts of the same Jetty (hence, cross-context). When creating a new Session object, a new JSESSIONID value is chosen. If getCrossContextSessionIDs() returns true, then it'll check if the current JSESSIONID value was created by this Jetty (including all other contexts) and if it was, it'll reuse it.

Since I'm dealing with two different Jetty instances running on two different ports, I'll need to hack Jetty's source to not do that check, or just make my own session-like framework.

查看更多
干净又极端
5楼-- · 2020-02-28 04:38

You could also set the jsessionid cookie path, I believe.

查看更多
▲ chillily
6楼-- · 2020-02-28 04:39

In our case we are using Tomcat, so the solution is to use different session cookie names on each instance.

In context.xml do something like

<Context sessionCookieName="JSessionId_8080">
查看更多
欢心
7楼-- · 2020-02-28 04:40

I had a similar problem: One or more instances of the same application on localhost on different ports, choosen at application start time, each using its own jetty instance.

After a while, I came up with this:

  • Wait for jetty to initialize
  • use jetty's SocketManager to get the port (socketManager.getLocalPort())
  • set the cookie name through the SessionManager (sessionHandler.getSessionManager().setSessionCookie(String))

This way I have a difference cookie name for each instance - thus no interference anymore.

查看更多
登录 后发表回答