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