我有一个应用程序,该应用程序存储了已经使用了多年的会话授权详细信息,现在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重写可以解决此问题,但是为什么这突然中断了?
非常感谢您的帮助!
答案 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 /会话,因此无法访问该会话。