2012-01-24 36 views
0

我需要获取当前会话ID而不触及会话(以使其有机会过期)。在没有使用cookie访问会话的情况下获取sessionId

我已经使用来自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的代码会使会话保持活动状态并且不会超时!

编辑

我真的stucked!我已经尝试afilter将删除JSESSIONID饼干和来自HttpServletRequest删除所有cookie,但是当我在请求调用的getSession(假)传递到该servlet,我得到了一个有效的会话!

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[] {}); 
     } 

    } 

而且真的想忘记所有关于会话,只使用会话ID只是一个唯一的标识符给用户,并自己做了艰辛的道路。

回答

5

至于你的代码,不要这么做,用HttpServletRequest#getRequestedSessionId()HttpServletRequest#isRequestedSessionIdValid()来检查请求的会话ID是否有效。

if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) { 
    // The session has been expired (or a hacker supplied a fake cookie). 
} 

至于你的具体问题:

访问饼干的代码使会话保持活跃并没有超时!

不,代码没有这样做。这就是HTTP请求本身。不是每当你不打电话getSession()什么的,都不会推迟会话超时。无论您是否需要代码中的会话,它都会在客户端发起的每个HTTP请求中推迟。

要了解会议是如何工作的,你会发现这个答案有帮助:How do servlets work? Instantiation, sessions, shared variables and multithreading

+0

是的,但与'HttpServletRequest#isRequestedSessionIdValid()' –

+0

@nico:是的,我现在也看到了什么OP意图实现。我更新了答案。 – BalusC

1

会话期满不依赖于代码访问会话,这取决于发出请求与用户那届会议。每次用户发出请求时,会话的超时时间都会重置。

如果你想有将用户的请求重新设置超时(即有固定长度的会话),那么你就需要为配置会话,包括可能使用不同的过滤器做额外的事处理会话。

+0

我已经添加了一个过滤器(如上所示),但在请求到达任何过滤器/ servlet之前似乎正在创建会话对象(基于'cookie'头部),这是合乎逻辑的。 –

0

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

相关问题