Google App Engine会话丢失属性

时间:2018-06-25 00:27:34

标签: java google-app-engine

我有一个应用程序,该应用程序存储了已经使用了多年的会话授权详细信息,现在session属性返回的是null。我在每个请求的开头检索会话数据,并在返回响应之前进行设置。该应用程序是基于GAE标准运行的Spring 3 MVC。

会话已启用,<sessions-enabled>true</sessions-enabled>。我所有的对象都实现了Serializable。 更新-在检查项目历史记录时,我最近升级到Java8。我恢复为Java 7,并且在设置会话后,该会话仍返回null属性。重新设置为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;
}

在进行故障排除时,我添加了<async-session-persistence enabled="true" />,并删除了它,因为会话数据也用于导航。

更新-用户报告他们能够与某些浏览器/平台(而非其他浏览器/平台)保持会话,这使我相信这与Cookie相关。禁用会话cookie时,我可以重复该问题。 URL重写可以解决此问题,但是为什么这突然中断了?

非常感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

我按照public issue tracker的建议提交了Ggrimaldo的请求。

他们确认,这很可能是与浏览器相关的问题,因为在某些浏览器和平台上会话不会丢失。他们建议设置带有会话ID的cookie,如果会话数据为null,则读取会话ID。我发现这个post描述了如何从数据存储中读取_ah_session数据,并以此方式实现了

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);
}

从这里打电话

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);
}

我将要求我的用户重试并稍微看一下日志。这一直是一个特别烦人的问题,但是由于我作为俱乐部的志愿者维护此网站,所以任何希望进行维护的人都不会抱怨。我将发布更新。如果jsessionid易变,我将不得不创建自己的cookie(argh)。

嗯,这是我的cookie设置代码,是从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);
}

我在首次建立会话时进行设置,并在每次保存会话时进行更新。每当会话属性保存在会话中时,还有一些其他条件逻辑可用于设置或更新cookie中的会话值。它正在工作,我的用户很高兴。

首先没有明显的原因,所以希望没有人会遇到。我愿意,可以投赞成票或发表评论,这样我就知道是不是我,谢谢!

答案 1 :(得分:0)

在我使用Python / Flask进行开发时可能无关紧要,但是由于我错误地将应用程序“秘密密钥”设置为在每个实例上随机生成的内容,因此我失去了会话。这意味着当用户从一个实例转移到另一个实例时,由于每个实例都使用不同的密钥来签名cookie /会话,因此无法访问该会话。