對于所有 Web 應(yīng)用程序來說,安全是非常重要的。一個(gè)安全問題是當(dāng)變量超出會話范圍時(shí)您可能需要考慮限制用戶訪問 Web 應(yīng)用程序的特殊頁面。出現(xiàn)這個(gè)問題時(shí),您可能想要求用戶再次登錄,然后才能繼續(xù)。
|
本技巧適用于以下技術(shù)和資源
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
|
不需要
|
* 到發(fā)布本文時(shí)止,Sun Java System Application Server 只支持 Java EE 5。
現(xiàn)在,本文中的技巧已適用于 Sun Java Application Server PE 9.0 Update Release 1 和 Tomcat 5.5.17。如果您使用其他服務(wù)器,請查看發(fā)行說明和 FAQ 了解已知問題和解決辦法。有關(guān)所支持服務(wù)器和 Java EE 平臺的詳細(xì)信息,請參閱發(fā)行說明。
概述
本技巧介紹當(dāng)會話超時(shí)或達(dá)到空值時(shí)您如何將該用戶重定向到另一個(gè)頁面。在這種情況下,您希望在加載頁面時(shí)執(zhí)行重定向。但是使用超級鏈接不起作用,按鈕動作處理器方法的標(biāo)準(zhǔn)代碼也不起作用。
處理該情況的最可靠方法是使用 Servlet Filter。而且使用 Servlet Filter 還非常高效,因?yàn)橐坏┰O(shè)置了此過濾器,您便可以在項(xiàng)目中的任何頁面或組件中使用。同時(shí)您還可以為按鈕動作處理器方法編寫自定義代碼,后一種方法不如前面的方法可靠,原因是該方法取決于 web.xml 文件中的設(shè)置。修改后的動作處理器代碼還必須包含于您要測試會話是否超時(shí)的所有頁面上。盡管本技巧介紹如何修改按鈕動作處理器,但建議您盡可能使用 Servlet Filter 方法。
無論您選擇哪種方法,要使代碼正常工作,您還需要在 web.xml 文件中設(shè)置一個(gè)會話超時(shí)值;例如,將會話超時(shí)值設(shè)置為 1 分鐘:
<session-config>
<session-timeout>1</session-timeout>
</session-config>
創(chuàng)建一個(gè)具有兩頁的項(xiàng)目
您可以自己輕松創(chuàng)建此示例。在您的可視 Web 應(yīng)用程序中設(shè)置兩個(gè)頁面:頁面1 具有一個(gè)按鈕和一個(gè)顯示會話超時(shí)消息的 ErrorPage。如果用戶在達(dá)到 web.xml 文件中設(shè)置的超時(shí)值之前,單擊頁面 1 上的按鈕,則不會發(fā)生任何事情(因?yàn)闀捝形闯瑫r(shí))。但是,如果已經(jīng)達(dá)到了超時(shí)值,即表示該會話已經(jīng)超時(shí),則該按鈕會將用戶帶到 ErrorPage。
請記住,當(dāng)會話超時(shí)時(shí)查看重定向是否正常工作,您必須等待超過您在 web.xml 文件中設(shè)置的超時(shí)值之后才能單擊該按鈕。
使用 Servlet Filter
當(dāng)會話超時(shí)時(shí)重定向用戶的最佳方法是使用 Servlet Filter。使用該方法,您不需要對按鈕動作處理器的代碼進(jìn)行任何修改。
常規(guī)步驟如下:
l 使用 GUI 創(chuàng)建一個(gè) Filter 類并將它的過濾器映射設(shè)置為 Servlet 和 Faces Servlet。
l 將 Servlet Filter 類中的代碼替換為自定義代碼。
l 部署項(xiàng)目。
下面是完成此操作的方法。
1. 首先,創(chuàng)建 Filter 類。在 NetBeans 6.0 中,右鍵單擊該項(xiàng)目,然后單擊 New -> Other 打開 File Type 對話框。(在 NetBeans 5.5 或 5.5.1 中,右鍵單擊該項(xiàng)目,然后單擊 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 并確保它設(shè)置為 Faces Servlet。然后單擊 Finish。
5. 現(xiàn)在,在源編輯器中打開 SessionCheckFilter 類,然后用以下代碼替換整個(gè)類。
代碼示例 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
方法進(jìn)行它的所有處理。它獲得對會話的參考并測試會話是否是新的會話或者用戶是否仍然在上一個(gè)會話中。如果是新的會話,則代碼會增加變量 firstRequest
,它表示這不再是新的會話。但是,如果用戶仍然位于相同的會話中并且該會話已經(jīng)超時(shí),則 Servlet Filter 會將該用戶重定向到一個(gè)設(shè)置為處理超時(shí)問題的頁面。在本例中,為 faces/ErrorPage.jsp
。
現(xiàn)在,您可以部署和運(yùn)行該項(xiàng)目了。當(dāng)您等待超過超時(shí)值(在本例中,為 1 分鐘)之后單擊主頁面上的按鈕時(shí),過濾器會將您重定向到錯誤頁面。無論您以前單擊該按鈕多少次,都會發(fā)生該重定向。還請注意,Servlet Filter 適用于任何頁面和任何組件。您不需要為頁面上的組件編寫任何特殊的代碼。
修改按鈕動作處理器方法
您也可以為按鈕動作處理器方法編寫一些自定義的代碼以在會話到期時(shí)將用戶重定向到另一個(gè)頁面。
除了設(shè)置超時(shí)值之外,要使該方法正常工作,還要確保將 web.xml 文件中的 javax.faces.STATE_SAVING_METHOD
參數(shù)設(shè)置為 client
。如果設(shè)置為 server
,則按鈕動作方法將永遠(yuǎn)也不會被調(diào)用,無論超時(shí)值的設(shè)置如何都是如此。要驗(yàn)證和更改此參數(shù)的設(shè)置,請展開 web.xml 文件的 Context Parameters 部分。如果 javax.faces.STATE_SAVING_METHOD
的值設(shè)置為 server
,請使用 Edit 按鈕將屬性值更改為 client
。
|
圖 3:設(shè)置 javax.faces.STATE_SAVING_METHOD 參數(shù)
|
所有關(guān)鍵代碼都位于按鈕動作處理器方法中。在 Java 源編輯器中打開 Page1 按鈕動作處理器方法,并向該方法中添加以下代碼。輸入該代碼之后,請使用 Fix Imports 函數(shù)導(dǎo)入該代碼使用的類。
代碼示例 2:用于會話超時(shí)重定向的按鈕動作處理器
|
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;
}
|
該動作處理器方法的關(guān)鍵部分位于開始部分。前三個(gè)方法為:
ExternalContext externalContext = getFacesContext().getExternalContext();
HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
HttpSession session = request.getSession();
為您提供一個(gè)該會話本身的處理器。
接下來,您檢查該會話是否是新會話,或者是否用戶仍然處于相同(上一個(gè))會話中。如果是新會話,則執(zhí)行 try 塊中的代碼;否則,用戶仍然處于相同會話中,并且動作處理器方法返回。try 塊中的重定向代碼如下:
if (session.isNew()) {
try {
String errorPageURL = externalContext.getRequestContextPath() +
"/faces/ErrorPage.jsp";
externalContext.redirect(errorPageURL);
上面的代碼建立了到您要重定向到的頁面的路徑,在本例中為錯誤頁面 ErrorPage.jsp
。路徑為 Web 應(yīng)用程序上下文和重定向到的頁面名稱的組合。代碼使用 ExternalContext.getRequestContextPath
方法返回請求 URI 的一部分,該部分標(biāo)識請求的 Web 應(yīng)用程序上下文,并且還向此上下文中附加重定向頁面的名稱 (/faces/ErrorPage.jsp
)。
然后,調(diào)用 ExternalContext
.redirect
方法,將它的絕對 URL 路徑傳遞給重定向頁面。redirect
方法將客戶端請求重定向到指定的 URL。它還在當(dāng)前請求的 FacesContext
實(shí)例上調(diào)用 responseComplete
方法。
小結(jié)
盡管兩種方法都可以正常工作,但很容易看出使用 Servlet Filter 是處理會話超時(shí)時(shí)重定向問題的最簡單方法。您不僅可以使用 IDE 對話框創(chuàng)建 Servlet Filter,使所需要添加的代碼非常簡單。而且使用 Servlet Filter 還不需要在要檢查會話是否超時(shí)的每個(gè)頁面上(或者包括在多個(gè)組件動作處理器中)重定向邏輯。