對于所有 Web 應用程序來說,安全是非常重要的。一個安全問題是當變量超出會話范圍時您可能需要考慮限制用戶訪問 Web 應用程序的特殊頁面。出現這個問題時,您可能想要求用戶再次登錄,然后才能繼續。
|
本技巧適用于以下技術和資源
NetBeans IDE 6.0、5.5.1 和 5.5
|
|
JavaServer Faces Components/ Java EE Platform
|
1.2 with Java EE 5* 1.1 with J2EE 1.4
|
Travel Database
|
不需要
|
BluePrints AJAX Component Library
|
不需要
|
* 到發布本文時止,Sun Java System Application Server 只支持 Java EE 5。
現在,本文中的技巧已適用于 Sun Java Application Server PE 9.0 Update Release 1 和 Tomcat 5.5.17。如果您使用其他服務器,請查看發行說明和 FAQ 了解已知問題和解決辦法。有關所支持服務器和 Java EE 平臺的詳細信息,請參閱發行說明。
概述
本技巧介紹當會話超時或達到空值時您如何將該用戶重定向到另一個頁面。在這種情況下,您希望在加載頁面時執行重定向。但是使用超級鏈接不起作用,按鈕動作處理器方法的標準代碼也不起作用。
處理該情況的最可靠方法是使用 Servlet Filter。而且使用 Servlet Filter 還非常高效,因為一旦設置了此過濾器,您便可以在項目中的任何頁面或組件中使用。同時您還可以為按鈕動作處理器方法編寫自定義代碼,后一種方法不如前面的方法可靠,原因是該方法取決于 web.xml 文件中的設置。修改后的動作處理器代碼還必須包含于您要測試會話是否超時的所有頁面上。盡管本技巧介紹如何修改按鈕動作處理器,但建議您盡可能使用 Servlet Filter 方法。
無論您選擇哪種方法,要使代碼正常工作,您還需要在 web.xml 文件中設置一個會話超時值;例如,將會話超時值設置為 1 分鐘:
<session-config>
<session-timeout>1</session-timeout>
</session-config>
創建一個具有兩頁的項目
您可以自己輕松創建此示例。在您的可視 Web 應用程序中設置兩個頁面:頁面1 具有一個按鈕和一個顯示會話超時消息的 ErrorPage。如果用戶在達到 web.xml 文件中設置的超時值之前,單擊頁面 1 上的按鈕,則不會發生任何事情(因為會話尚未超時)。但是,如果已經達到了超時值,即表示該會話已經超時,則該按鈕會將用戶帶到 ErrorPage。
請記住,當會話超時時查看重定向是否正常工作,您必須等待超過您在 web.xml 文件中設置的超時值之后才能單擊該按鈕。
使用 Servlet Filter
當會話超時時重定向用戶的最佳方法是使用 Servlet Filter。使用該方法,您不需要對按鈕動作處理器的代碼進行任何修改。
常規步驟如下:
l 使用 GUI 創建一個 Filter 類并將它的過濾器映射設置為 Servlet 和 Faces Servlet。
l 將 Servlet Filter 類中的代碼替換為自定義代碼。
l 部署項目。
下面是完成此操作的方法。
1. 首先,創建 Filter 類。在 NetBeans 6.0 中,右鍵單擊該項目,然后單擊 New -> Other 打開 File Type 對話框。(在 NetBeans 5.5 或 5.5.1 中,右鍵單擊該項目,然后單擊 New->File/Folder 可打開該對話框。)然后在該對話框屏幕的 Categories 列(如果它尚未高亮顯示)中選擇 Web,在 Files Type 列中選擇 Filter。單擊 Next。
2. 將顯示 New Filter 對話框。在 Class Name 中輸入 SessionCheckFilter,然后單擊 Next。(您可以為此過濾器使用任何名稱。)
3. 在 Configure Filter Deployment 對話框中,在 Filter Mappings 框(如果尚未高亮顯示)中選擇 SessionCheckFilter,然后單擊 Edit。
|
圖 1. Configure Filter Deployment 對話框 (單擊可放大圖像)
|
4. 在 Filter Mapping 對話框中,選中 Servlet 并確保它設置為 Faces Servlet。然后單擊 Finish。
5. 現在,在源編輯器中打開 SessionCheckFilter 類,然后用以下代碼替換整個類。
代碼示例 1:用于重定向的 SessionCheckFilter 代碼
|
public class SessionCheckFilter implements Filter {
private static int firstRequest = 0;
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest hreq = (HttpServletRequest)request;
HttpServletResponse hres = (HttpServletResponse)response; HttpSession session = hreq.getSession();
if (session.isNew()) {
if(firstRequest == 0){
firstRequest++;
} else {
hres.sendRedirect("faces/ErrorPage.jsp");
return;
}
}
chain.doFilter(request, response);
}
public void init(FilterConfig filterConfig) throws ServletException {} public void destroy() {}
}
|
Servlet Filter 采用 doFilter
方法進行它的所有處理。它獲得對會話的參考并測試會話是否是新的會話或者用戶是否仍然在上一個會話中。如果是新的會話,則代碼會增加變量 firstRequest
,它表示這不再是新的會話。但是,如果用戶仍然位于相同的會話中并且該會話已經超時,則 Servlet Filter 會將該用戶重定向到一個設置為處理超時問題的頁面。在本例中,為 faces/ErrorPage.jsp
。
現在,您可以部署和運行該項目了。當您等待超過超時值(在本例中,為 1 分鐘)之后單擊主頁面上的按鈕時,過濾器會將您重定向到錯誤頁面。無論您以前單擊該按鈕多少次,都會發生該重定向。還請注意,Servlet Filter 適用于任何頁面和任何組件。您不需要為頁面上的組件編寫任何特殊的代碼。
修改按鈕動作處理器方法
您也可以為按鈕動作處理器方法編寫一些自定義的代碼以在會話到期時將用戶重定向到另一個頁面。
除了設置超時值之外,要使該方法正常工作,還要確保將 web.xml 文件中的 javax.faces.STATE_SAVING_METHOD
參數設置為 client
。如果設置為 server
,則按鈕動作方法將永遠也不會被調用,無論超時值的設置如何都是如此。要驗證和更改此參數的設置,請展開 web.xml 文件的 Context Parameters 部分。如果 javax.faces.STATE_SAVING_METHOD
的值設置為 server
,請使用 Edit 按鈕將屬性值更改為 client
。
|
圖 3:設置 javax.faces.STATE_SAVING_METHOD 參數
|
所有關鍵代碼都位于按鈕動作處理器方法中。在 Java 源編輯器中打開 Page1 按鈕動作處理器方法,并向該方法中添加以下代碼。輸入該代碼之后,請使用 Fix Imports 函數導入該代碼使用的類。
代碼示例 2:用于會話超時重定向的按鈕動作處理器
|
public String button1_action() {
ExternalContext externalContext = getFacesContext().getExternalContext();
HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
HttpSession session = request.getSession();
if (session.isNew()) {
try {
String errorPageURL = externalContext.getRequestContextPath() +
"/faces/ErrorPage.jsp";
externalContext.redirect(errorPageURL);
} catch(IOException ioe) {
System.out.println("==============");
ioe.printStackTrace(System.out);
System.out.println(ioe.toString());
System.out.println("==============");
}
} else {
System.out.println("==============");
System.out.println("*** Session is not New ***");
System.out.println("==============");
}
return null;
}
|
該動作處理器方法的關鍵部分位于開始部分。前三個方法為:
ExternalContext externalContext = getFacesContext().getExternalContext();
HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
HttpSession session = request.getSession();
為您提供一個該會話本身的處理器。
接下來,您檢查該會話是否是新會話,或者是否用戶仍然處于相同(上一個)會話中。如果是新會話,則執行 try 塊中的代碼;否則,用戶仍然處于相同會話中,并且動作處理器方法返回。try 塊中的重定向代碼如下:
if (session.isNew()) {
try {
String errorPageURL = externalContext.getRequestContextPath() +
"/faces/ErrorPage.jsp";
externalContext.redirect(errorPageURL);
上面的代碼建立了到您要重定向到的頁面的路徑,在本例中為錯誤頁面 ErrorPage.jsp
。路徑為 Web 應用程序上下文和重定向到的頁面名稱的組合。代碼使用 ExternalContext.getRequestContextPath
方法返回請求 URI 的一部分,該部分標識請求的 Web 應用程序上下文,并且還向此上下文中附加重定向頁面的名稱 (/faces/ErrorPage.jsp
)。
然后,調用 ExternalContext
.redirect
方法,將它的絕對 URL 路徑傳遞給重定向頁面。redirect
方法將客戶端請求重定向到指定的 URL。它還在當前請求的 FacesContext
實例上調用 responseComplete
方法。
小結
盡管兩種方法都可以正常工作,但很容易看出使用 Servlet Filter 是處理會話超時時重定向問題的最簡單方法。您不僅可以使用 IDE 對話框創建 Servlet Filter,使所需要添加的代碼非常簡單。而且使用 Servlet Filter 還不需要在要檢查會話是否超時的每個頁面上(或者包括在多個組件動作處理器中)重定向邏輯。