2012-01-24 66 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

會話不是超時,這是正確的行爲,因爲在任何情況下都會接受請求並更新會話過期。

相關問題