在不使用cookie API访问会话的情况下获取sessionId

时间:2012-01-24 13:19:28

标签: java servlets cookies session-timeout

我需要获取当前会话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作为用户的唯一标识符,并且自己很难完成。

3 个答案:

答案 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)

会话不是超时,这是正确的行为,因为请求已被接受,并且会话到期在任何情况下都会更新。