1

I have an application that stores session authorization details that has been working for years, now the session attribute is returning null. I retrieve the session data at the beginning of every request, and set it before returning the response. The application is Spring 3 MVC running on GAE standard.

Sessions are enabled, <sessions-enabled>true</sessions-enabled>. All of my objects implement Serializable. UPDATE - In checking the project history, I recently upgraded to Java 8. I reverted to Java 7, and the session is still returning a null attribute after being set. Set back to Java 8.

protected void setSessionAccess(HttpServletRequest request, Access access) {
    logger.info("setting session access...");
    request.getSession().setAttribute(ACCESS, access);
}

protected Access getSessionAccess(HttpServletRequest request) {
    logger.info("getting session access...");
    Access access = (Access) request.getSession().getAttribute(ACCESS);
    if (access == null) {
        logger.log(Level.WARNING, "access is null, initializing access...");
        access = new Access();
    }
    return access;
}

While troubleshooting, I had added <async-session-persistence enabled="true" />, and removed it because the session data is also used for navigation purposes.

UPDATE - Users are reporting they're able to maintain session with some browsers/platforms, and not others, leading me to believe this is cookie related. I can duplicate the issue when I disable session cookies. URL rewriting would resolve this issue, but why did this break all of a sudden?

Any help is greatly appreciated!

Neill
  • 556
  • 2
  • 8
  • 18
  • I think it is very strange that your app had stopped working out of the sudden without you doing any change to it. The only thing that comes to my mind is that the internal VM or libraries of App Engine had experienced a substantial change that disrupts the normal function of your App. Have you reviewed the [release notes](https://cloud.google.com/appengine/docs/standard/java/release-notes) to find if they could be related? – Ggrimaldo Jun 25 '18 at 11:06
  • I tried a number of things and was getting desperate, this has been going on for a week. Literally, the only thing that restored operation was deleting the _ah_SESSION entities in the Datastore. I was ready to deploy a new app with the same code to see if there was something in the application setup and configuration. My users will be pleased to know that can now use the application . The application is about 5 years old through several iterations. Will be going to RESTful services and maybe Docker and CI, soon, cheers! I'll be miserable if this application hiccups, again. – Neill Jun 25 '18 at 11:30
  • I hope this fixed it, good luck!. You can always contact the official support if this gets too tricky though – Ggrimaldo Jun 25 '18 at 14:16
  • I have some users still complaining about losing their authentication, mine and one other person's works fine, but the logs are showing some session attributes getting lost. I thought Google had transitioned their product groups to StackOverflow. I've never contacted Google directly for support, but I may have to look into it. – Neill Jun 26 '18 at 01:46
  • Indeed it is like this, I am with GCP support. However not everything can be answered in SO as many issues do require an deeper analisys of the code, instances/configuration used, logs,etc, which are not possible to see in Stackoverflow. If it is still going on, you may want to open a ticket within the [Support Center](https://support.google.com/googlecloud/answer/1041916?hl=en) if you have a support plan. Alternatively, you can use the [public issue tracker](https://issuetracker.google.com). – Ggrimaldo Jun 28 '18 at 15:31

2 Answers2

3

Could be unrelated as I'm developing in Python/Flask, but I was losing my sessions as I had incorrectly set the application "secret key" to something randomly generated on each instance. This meant as the user was transferred from instance to instance the session was unable to be accessed as each instance had a different key it was signing cookies/sessions with.

Ari
  • 5,301
  • 8
  • 46
  • 120
0

I submitted a request with the public issue tracker as Ggrimaldo suggests.

They confirmed it's most likely a browser related issue, since sessions aren't lost with some browsers and platforms. They suggested setting a cookie with the session id, and reading the session id if the session data was null. I found this post describing how to read the _ah_session data from the datastore, and implemented it this way,

try {
    DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
    Key sessionKey = KeyFactory.createKey("_ah_SESSION", "_ahs" + sessionId);
    Entity sessionEntity = datastore.get(sessionKey);
    Blob blob = (Blob) sessionEntity.getProperty(_VALUES);
    byte[] sessionBytes = blob.getBytes();

    ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(sessionBytes);
    ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
    return (Map<String, Object>) objectInputStream.readObject();
} catch (EntityNotFoundException e) {   
    logger.log(Level.INFO, e.getMessage());
} catch (Exception e) {
    logger.log(Level.SEVERE, e.getMessage(), e);
}

called from here,

String mySessionId = null;
for (Cookie cookie : cookies) {
    if ("MYSESSIONID".equals(cookie.getName())) {
        mySessionId = cookie.getValue();
    }
}
// returning code is above
sessionMap = gcpSessionService.getGcpSession(swgcSessionId);
if (sessionMap != null) {
    access = (Access) sessionMap.get(ACCESS);
}

I'll ask my users to retry and watch the logs a bit. This has been a particularly annoying issue, but since I maintain this site as a volunteer for a club, no complaints from anyone wanting to take up maintenance. I'll post an update. If the jsessionid is volatile, I'll have to resort to creating my own cookie (argh).

So, argh, here's my cookie setting code, copied from elsewhere on stackoverflow,

protected void setMySessionCookie(HttpServletResponse response, String jSessionId) {

    logger.log(Level.INFO, "setting MYSESSIONID = " + jSessionId);

    final String cookieName = "MYSESSIONID";
    // you could assign it some encoded value
    final String cookieValue = jSessionId; 
    // TODO enforce SSL
    final Boolean useSecureCookie = false; 
    final int expiryTime = -1; // 24h in seconds
    final String cookiePath = "/";

    Cookie cookie = new Cookie(cookieName, cookieValue);
    // determines whether the cookie should only be sent using a secure protocol, such as HTTPS or SSL
    cookie.setSecure(useSecureCookie);
    // A negative value means that the cookie is not stored persistently and will be deleted when the Web browser exits. A zero value causes the cookie to be deleted.
    cookie.setMaxAge(expiryTime);
    // The cookie is visible to all the pages in the directory you specify, and all the pages in that directory's subdirectories
    cookie.setPath(cookiePath);

    response.addCookie(cookie);
}

I set this when the session is first established, and update it each time the session is saved. There's some additional conditional logic for setting or updating the session value in the cookie each time the session attribute is saved in the session. It's working and my users are happy.

There's no obvious reason why this occurred in the first place, so hopefully no one will run into it. I you do, vote up or leave a comment so I get an idea if it's just me, thanks!

Neill
  • 556
  • 2
  • 8
  • 18