2013-03-22 73 views
10

我一直在看這個主題的很多帖子,但無法得到一個解決方案,在我的情況。HttpSession超時後重定向

我使用的Java EE 6的JSF 2.0(部署在JBoss AS 7.1)

在我web.xml我:

<session-config> 
     <session-timeout>1</session-timeout> 
    </session-config> 

和我希望用戶被重定向到登錄頁面當會話自動超時。

我曾嘗試:

方法1:使用過濾器

我曾嘗試以下過濾器:

@WebFilter() 
public class TimeOutFilter implements Filter { 

     @Override 
     public void init(FilterConfig filterConfig) throws ServletException { 
     } 

     @Override 
     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, 
     ServletException { 
     System.out.println("filter called"); 
     final HttpServletRequest req = (HttpServletRequest) request; 
     final HttpSession session = req.getSession(false); 
     if (session != null && !session.isNew()) { 
      chain.doFilter(request, response); 
     } else { 
      System.out.println("Has timed out"); 
      req.getRequestDispatcher("/logon.xthml").forward(request, response); 
     } 
    } 

    @Override 
    public void destroy() { 
    } 
} 

web.xml我試圖

<filter-mapping> 
    <filter-name>TimeOutFilter</filter-name> 
    <url-pattern>*.xhtml</url-pattern> 
</filter-mapping> 

<filter-mapping> 
    <filter-name>TimeOutFilter</filter-name> 
    <servlet-name>Faces Servlet</servlet-name> 
</filter-mapping> 

該過濾器在每次請求時調用(在控制檯中記錄「fiter called」)。 但會話超時時不會調用它。

方法2:HttpSessionLister

我曾嘗試使用HttpSessionListerner。該方法稱爲具有以下簽名:

public void sessionDestroyed(HttpSessionEvent se) { 
} 

我無法重定向到特定頁面。當我想重定向用戶時,我通常使用FacesContext中的NavigationHandler,但在這種情況下不存在FacesContextFacesContext.getCurrentInstance()返回null)。

根據此post,HttpListener不能重定向用戶,因爲它不是請求的一部分。

問題

什麼是去解決這個問題的最好方法是什麼?我能做些什麼來使上述兩種方法中的一種起作用?

+1

相關:http://stackoverflow.com/q/ 4992526/1065197 – 2013-03-22 14:50:48

+0

@LuiggiMendoza:非常感謝。雖然我從來沒有見過'ViewExpiredException',並且我希望(如果可能)重定向到登錄頁面,而用戶不必點擊任何東西。 – phoenix7360 2013-03-22 14:55:39

+0

您需要在客戶端進行某種形式的輪詢以觸發服務器端的302。一個心跳... – 2013-03-22 14:56:44

回答

15

只要客戶端沒有發送HTTP請求,就不能發送HTTP響應。就那麼簡單。這就是HTTP的工作原理。如果任何網站能夠在沒有客戶請求的情況下不經意地推送HTTP響應,那麼互聯網將會非常不同。基於

基於

一個JavaScript心跳在客戶端的鍵盤/鼠標活動等作爲回答here或間refresh頭部等作爲回答here如果你已經基本上是一個單頁web應用(因此將是解決辦法,你很有效不使用會話作用域,而是使用視圖作用域),但如果您在同一會話中的多個選項卡/窗口中打開了頁面,那麼這將不會很好地工作。

Websockets理論上是將某些東西推送給客戶端的正確解決方案,但這需要反過來一個活動會話。雞蛋問題。另外,它在目前仍然使用相對廣泛的舊版瀏覽器中不起作用,因此它目前僅適用於漸進式增強。

最好的辦法就是定義一個錯誤頁面,它處理終端用戶在會話過期時調用操作的情況。另見javax.faces.application.ViewExpiredException: View could not be restored

+1

我現在看到我的誤解。我不需要自動重定向用戶,而是需要讓用戶知道是否在會話超時後執行操作。 – phoenix7360 2013-03-22 15:14:06

-1

我知道您使用的是java-EE6和JSF,但是如果您可以嘗試使用JSP代碼或將以下代碼轉換爲在servlet中工作。假設您正在使用用戶名來檢查會話,請在web.xml文件中設置session-timeout。請注意,JSP代碼和servlet代碼是相似的。 驗證會話的代碼可能如下所示(JSP格式) 如果用戶名充當數據庫中的主鍵。

<% 
    String un = (String)session.getAttribute("un"); 

    if(un == null){ 
    response.sendRedirect(login page); 
    return; 
}else{ 
     code to process login form 
} 
    %> 

servlet代碼可能看起來像這樣

String un = (String)session.getAttribute("un"); 
if(un == null){ 
    response.sendRedirect(loginPage); 
} 
0

在HttpSessionListerner你不能發送給用戶任何迴應。實現此目的的一個好方法是使用輪詢,瀏覽器定期發送HTTP請求並立即收到響應。
有很多方法可以做到這一點:

  1. 您可以使用普通的老JavaScript來輪詢:這將在跨瀏覽器的環境中工作。

    函數刷新(){

    // make Ajax call here, inside the callback call: 
    
    setTimeout(refresh, 5000); 
    
    // ... 
    

    }

    // initial call, or just call refresh directly 
    

    的setTimeout(刷新,5000);

  2. 您可以使用Web套接字。網絡插座規格上存在以下鏈接:

    http://dev.w3.org/html5/websockets/

-1

你可以使用一個過濾器,並做如下測試:

HttpSession session = request.getSession(false); 
if(session != null && !session.isNew()) { 
    chain.doFilter(request, response); 
} 
else {enter code here 
    response.sendRedirect("/login.jsp"); 
}