How to share sessions between modules on a Google

2020-07-17 16:45发布

问题:

When I store something in the session via HttpSession in module A:

HttpSession session = req.getSession(true);
session.setAttribute("username", "Eng.Fouad");

then I try to retrieve this information from within module B (during the same browser session):

HttpSession session = req.getSession(true);
String username = session.getAttribute("username"); // null!

I got null as a value, which means different session.

How to share session across multiple modules in GAE?


Old Answer which I think it doesn't work well:

I've been trying to solving this issue for weeks. It turns out that the modules don't share sessions because the cookies are different across different sub-domains (module1.apphost.com cookies != module2.apphost.com cookies). To solve it, simply set cookies domain in web.xml of each module:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
         http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         id="WebApp_ID" version="2.5">

  <context-param>
    <param-name>org.mortbay.jetty.servlet.SessionDomain</param-name>
    <param-value>.apphost.com</param-value>
  </context-param>
  <context-param>
    <param-name>org.mortbay.jetty.servlet.SessionPath</param-name>
    <param-value>/</param-value>
  </context-param>
  <context-param>
    <param-name>org.mortbay.jetty.servlet.SessionURL</param-name>
    <param-value>none</param-value>
  </context-param>

  ...

</web-app>

EXTRA:

Here is a list of all init parameters you can use with Jetty cookies:


EDIT: Workaround for development environment:

  1. Make the port of each module fixed (using JVM arg -Dcom.google.appengine.devappserver_module.{module_name}.port=8081). For example, module1 is always hosted at localhost:8888, and module2 is always hosted at localhost:8889. See this answer.
  2. Bind the localhost with the port of each module to a custom domain using Fiddler. For example, moule1.gaelocal.com points to localhost:8888 and moule2.gaelocal.com points to localhost:8889. See this answer.
  3. Update web.xml of each module and replace .apphost.com with .gaelocal.com (or just use .apphost.com for both environment).

回答1:

You can implement a combination of HttpServletFilter and HttpSessionListener that synchronizes accross both webapps. When a request modifies session state, save it to a persistent store (db), and for each requests, checks if the session objects are up to date with db.

Note that this require both web app to be served under the same domain (eg: mydomain.com/webapp1 and mydomain.com/webapp2). Otherwise the JSESSIONID cookie wouldn't be delivered by the browser.

There's an off the shelf solution that does this such as Hazelcast. It's designed for load balancing / failover but you might be able to use it for the intended purpose.

Also consider the possibility using HttpSession is a wrong architectural design. Maybe you should be transacting with a database / API instead?



回答2:

HttpSession is inteded for use in a monolithich environment in which the servlet container has contact directly with a singular client. One implementation suggestion is to use a database API to store the current state of the client session. Since you are using GAE, Google's datastore come to mind.

https://cloud.google.com/appengine/docs/java/gettingstarted/usingdatastore



回答3:

I am just a beginner. But still you could try setting the domain for the cookie in your config file and retrieve sessions from there.

<context-param>
    <param-name>root_path</param-name>
    <param-value>/portal</param-value>  
</context-param>
...
...
<session-config>
    <cookie-config>
      <http-only>true</http-only>
    </cookie-config>
    <tracking-mode>COOKIE</tracking-mode>
</session-config>

I hope this helps.

May be this link is helpful for you.

share-session-data-between-2-subdomains