18

这个问题与我的另一个问题“ Java Web 应用程序中的会话过期时如何重定向到登录页面? ”有关。以下是我正在尝试做的事情:

  1. 我有一个在 JBoss AS 5 上运行的 JSF Web 应用程序
  2. 当用户处于非活动状态时,比如说 15 分钟,如果他在会话过期后尝试使用应用程序,我需要注销用户并将他重定向到登录页面。
  3. 因此,正如“ JSF 注销和重定向”中所建议的那样,我已经实现了一个过滤器,该过滤器检查会话过期条件,如果会话过期,则将用户重定向到 session-timed-out.jsp 页面。
  4. 我在 web.xml 中的所有其他过滤器定义之上添加了 SessionExpiryCheckFilter,这样我的会话到期检查将始终得到第一个命中。

现在是我面临的挑战。由于我使用的是 JBoss AS,当会话过期时,JBoss 会自动将我重定向到登录页面(请注意,不会调用会话过期检查过滤器)。因此,在我登录后,我的 SessionExpiryCheckFilter 拦截了请求,它看到一个会话可用。但是,它抛出异常javax.faces.application.ViewExpiredException: viewId:/mypage.faces - View /mypage.faces could not be restored.

以前有人遇到过这个问题吗?有什么想法可以解决这个问题吗?

4

5 回答 5

14

以下方法对我有用。请注意,您必须使用 JSTL 核心 taglib 重定向而不是 jsp 重定向才能使其正常工作(因为 jsp 也会过期)。

在您的FacesConfig.xml 中,您输入以下内容:

<error-page>
    <exception-type>javax.faces.application.ViewExpiredException</exception-type>
    <location>/sessionExpired.jsf</location>
</error-page>

sessionExpired.jsp

<%@page contentType="text/html" pageEncoding="UTF-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<c:redirect url="/login.jsf" />

您也可以将此方法用于其他错误类型或异常。例如,该元素包含错误代码或异常类型与 Web 应用程序中资源路径之间的映射:

<error-page>
    <error-code>400</error-code>
    <location>/400.html</location>
</error-page>

or 元素包含 Java 异常类型的完全限定类名。

<error-page>
    <exception-type>javax.servlet.ServletException</exception-type>
    <location>/servlet/ErrorDisplay</location>
</error-page>
于 2009-08-24T21:31:44.807 回答
3

如果您使用的是 Mojarra/Sun RI,您可能想尝试将其添加到您的 web.xml:

<context-param>
    <param-name>com.sun.faces.enableRestoreView11Compatibility</param-name> 
    <param-value>true</param-value>
</context-param>

但是请注意,这并不总是完美的解决方案。它隐藏了用户丢失会话的事实。

于 2010-10-29T07:17:03.863 回答
1

为恢复视图实现 javax.faces.event.PhaseListener

@Override
public void afterPhase(PhaseEvent event) {
    FacesContext facesContext = event.getFacesContext();
     if(facesContext.getViewRoot()==null){   
       try{   
           facesContext.getExternalContext().redirect(HOME_PAGE);   
           facesContext.responseComplete();   
       } catch (IOException e){   
           e.printStackTrace();   
       }   
     }
}

@Override
public void beforePhase(PhaseEvent event) {}

@Override
public PhaseId getPhaseId() {
    return PhaseId.RESTORE_VIEW;
}

在 faces-config.xml 中注册

于 2011-06-27T21:22:19.757 回答
0

我建议结合过滤器编写会话侦听器。

当会话到期时,您可以创建一个新的会话对象并在新对象上设置一个超时值。

只需检查过滤器中的超时值并重定向浏览器。

http://www.java2s.com/Code/Java/Servlets/Servletsessionlistener.htm

于 2009-08-24T20:22:53.590 回答
0

我试图为它写一个过滤器,但有些它对我不起作用,所以我为它做了一个替代品。

我在我不希望用户在没有登录的情况下访问的每个页面中都这样做:

<f:view>
    <h:dataTable value="#{userHome.validuser()}"/>
     // my code
<f:view/>

这将调用validuser()我的会话托管 bean 中的函数。

现在这是我的功能。在登录期间,我已经将用户对象插入到会话中。

public void validuser()
{
     FacesContext context = FacesContext.getCurrentInstance();
    UserLogin ul = (UserLogin) context.getExternalContext().getSessionMap().get("userbean");

     if (ul == null)
         try{
                context.getExternalContext().redirect("/HIBJSF/faces/LoginPage.xhtml");
                context.responseComplete();
        }
         catch (IOException e)
        {
         e.printStackTrace();
        }
} 

如果有会话但没有人登录,那么它将带您到重定向页面。

于 2011-10-13T12:21:12.083 回答