对于所有 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 还不需要在要检查会话是否超时的每个页面上(或者包括在多个组件动作处理器中)重定向逻辑。