我需要获取当前会话ID而不会访问会话(以使其有机会到期)。
我使用了来自Servlet代码的Cookie,以保持会话未被触及,然后在超时时间后使会话过期。
我使用以下代码:
public static String getSessionId(HttpServletRequest request)
{
String sessionId = "";
String logMsg = "";
if (request != null)
{
String sessionTimeout = PropertiesReader.SESSION_TIMEOUT_SCHEMA;
if (sessionTimeout != null && SessionHelper.SESSION_TIMEOUT_FIXED.equalsIgnoreCase(sessionTimeout))
{
logMsg = "FIXED: Getting SessionId from Cookies with activating the session";
Cookie[] cookies = request.getCookies();
if (cookies != null)
{
for (Cookie cook : cookies)
{
if ("JSESSIONID".equalsIgnoreCase(cook.getName()))
{
sessionId = cook.getValue();
break;
}
}
}
} else
{
logMsg = "PER_USAGE: Getting SessionId from Session";
sessionId = request.getSession(false) != null ? request.getSession(false).getId() : "";
}
}else
{
logMsg = "Request object is null";
}
logger.info(logMsg + ", sessionId=" + sessionId);
return sessionId;
}
一台OC4J应用服务器,它运行正常。虽然在另一个oc4j服务器上,访问cookie的代码使会话保持活动状态,但不会超时!
修改:
我真的坚持了!,我试图放置afilter来移除JSESSIONID cookie并从HttpServletRequest中删除所有cookie,但是当我在传递给servlet的请求上调用getSession(false)时,我得到了一个有效的Session!
class CookieRemovalHttpServletRequestWrapper extends HttpServletRequestWrapper
{
public static final String COOKIE_HEADER = "cookie";
public static final String JSESSIONID = "JSESSIONID";
public CookieRemovalHttpServletRequestWrapper(HttpServletRequest request)
{
super(request);
}
@Override
public String getHeader(String name)
{
if (COOKIE_HEADER.equalsIgnoreCase(name))
{
return "";
}
return super.getHeader(name);
}
@Override
public Enumeration getHeaderNames()
{
Enumeration e = super.getHeaderNames();
List l = new ArrayList();
while (e.hasMoreElements())
{
String headerName = (String) e.nextElement();
if (!COOKIE_HEADER.equalsIgnoreCase(headerName))
{
l.add(headerName);
}
}
return Collections.enumeration(l);
}
@Override
public Enumeration getHeaders(String name)
{
if (COOKIE_HEADER.equalsIgnoreCase(name))
{
return new Enumeration()
{
public boolean hasMoreElements()
{
return false;
}
public Object nextElement()
{
return null;
}
};
}
return super.getHeaders(name);
}
@Override
public Cookie[] getCookies()
{
Cookie[] cs = super.getCookies();
List<Cookie> cokRet = new ArrayList<Cookie>(cs.length);
for (Cookie c : cs)
{
if (c.getName().equalsIgnoreCase(JSESSIONID)) continue;
cokRet.add(c);
}
return cokRet.toArray(new Cookie[] {});
}
}
并且真的想要忘记关于Session的所有内容并且只使用会话ID作为用户的唯一标识符,并且自己很难完成。
答案 0 :(得分:5)
关于您的代码,请不要这么做,请使用HttpServletRequest#getRequestedSessionId()
和HttpServletRequest#isRequestedSessionIdValid()
来检查所请求的会话ID以及它是否有效。
if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) {
// The session has been expired (or a hacker supplied a fake cookie).
}
关于你的具体问题:
访问cookie的代码使会话保持活动状态,不会超时!
不,代码不这样做。这是HTTP请求本身就是这样做的。如果您不调用getSession()
或其他内容,则不会推迟会话超时。无论您是否需要代码中的会话,它都会在客户端触发的每个HTTP请求上推迟。
要了解会话的工作原理,您可能会发现此答案很有用:How do servlets work? Instantiation, sessions, shared variables and multithreading
答案 1 :(得分:1)
会话过期不依赖于访问会话的您的代码,它取决于用户使用该会话发出请求。每次用户发出请求时,会话的超时都将自行重置。
如果你想不让用户的请求重新设置超时(即有一个固定长度的会话),那么你需要做更多配置会话的事情,包括可能的使用不同的过滤器来处理会话。
答案 2 :(得分:0)
会话不是超时,这是正确的行为,因为请求已被接受,并且会话到期在任何情况下都会更新。