【问题标题】:Failing to redirect from JSF phaselistener无法从 JSF phaselistener 重定向
【发布时间】:2011-12-20 08:38:29
【问题描述】:

我的问题与here 类似,但不涉及PrimeFaces。另外,我在那里找不到真正的解决方案。

我基本上是在尝试让 phaselistener 重定向到登录页面,以防没有 JSF 会话(例如,当会话超时时)

我正在尝试从 JSF 2 Phaselistener 中重定向。总结一下,我在做的是这样的:

public void beforePhase(PhaseEvent event) {
    PhaseId id = event.getPhaseId();
    if(id.equals(PhaseId.RESTORE_VIEW)){
        FacesContext context = event.getFacesContext();
        Map<String, Object> sessionMap = context.getExternalContext().getSessionMap();
        if(sessionMap==null || sessionMap.isEmpty()){
            // No Session, Redirect to login
            try {
                context.getExternalContext().redirect("/login");
            } catch (Exception e) {
                ...
            }
        }
    }
}

当重定向代码运行时,我得到了这个异常:

java.lang.NullPointerException
        at org.apache.myfaces.context.servlet.PartialViewContextImpl.getPartialResponseWriter(PartialViewContextImpl.java:301)
        at org.apache.myfaces.context.servlet.ServletExternalContextImpl.redirect(ServletExternalContextImpl.java:452)
        at com.AuthenticationPhaseListener.userIsNotLogedIn

这可能是什么原因造成的?我做错了吗?

谢谢!

【问题讨论】:

    标签: http jsf redirect jsf-2


    【解决方案1】:

    这似乎是在 ajax 请求期间发生的。我不确定确切的原因,堆栈跟踪至少表明 MyFaces 实现中可能存在错误。

    至少,整体设计方法很差。这种 HTTP 请求/响应修改最好PhaseListener 中进行。它不适合在那里。你想用普通的servlet Filter 来做这种工作。

    【讨论】:

    • 但是如何从过滤器中检查 JSF 会话状态?
    • request.getSession(false)。 JSF 基本上是基本 Servlet API 之上的一个抽象层。 ExternalContext#getSessionMap() 映射到 HttpSession 的属性。
    【解决方案2】:

    好吧,我遇到了和你一样的问题,但我没有像你那样复杂地解决。我的步骤

    1) create a class that implements the PhaseListener
    import javax.faces.application.NavigationHandler;
    import javax.faces.context.FacesContext;
    import javax.faces.event.PhaseEvent;
    import javax.faces.event.PhaseId;
    import javax.faces.event.PhaseListener;
    
    /**
     *
     * @author fakumawah @date 09.03.2012
     */
    public class LoggedInCheck extends BackingBean implements PhaseListener
    {
    
    @Override`enter code here`
     public PhaseId getPhaseId()
      {
        return PhaseId.ANY_PHASE;
      }
    
      @Override
      public void beforePhase(PhaseEvent event)
      {
      }
    
      @Override
      public void afterPhase(PhaseEvent event)
      {
        FacesContext fc = event.getFacesContext();
        boolean loginPage = fc.getViewRoot().getViewId().lastIndexOf("login") > -1 ? true :     false;
        if (!loginPage && !loggedIn())
        {
          NavigationHandler nh = fc.getApplication().getNavigationHandler();
          nh.handleNavigation(fc, null, "gotologin");
        }
      }
    
      private boolean loggedIn()
      {
        return getSessionWrapper().isLoggedInAgain();
      }
    }
    

    很抱歉没有注释代码,但我想代码真的很容易理解。需要注意的最重要的事情是 afterPhase(..) 它检查我是否已登录或是否已经有会话。如果我不这样做,它会创建一个导航器并将我导航到登录页面

    2) 您的 isLoggedInAgain() 应该如下所示:

    /**
       * A method to check if Username is already logged in
       * @param username
       * @return 
       */
      public boolean isLoggedInAgain()
      {
        if (session != null) // Check if session is not null
        {
          if (session.isConnected()) // Check if session is connected   
          {
            return true;
            //destroyIfsLibrarySession();  // Session is available -> destroy session
          }
          else  // session is not available
          {
            logger.log(Level.SEVERE, "Already logged out");
            return false;
          }
        }
        return false;
      }
    

    因为我正在处理来自 Oracle CMSDK 的 LibrarySessions,所以我的会话测试看起来像这样。最重要的是以某种方式检查您的会话并给出真假,这取决于会话是否存在。

    3) 在 faces-config.xml 中配置监听器

    <!-- Phase-Listener to check if user is logged in or not -->
    <lifecycle>
        <phase-listener>com.mycompany.mypackagename.webapp.LoggedInCheck</phase-listener>
    </lifecycle>
    

    4) 最后为“gotologin”定义一个导航规则

    <!-- Navigation Rule for sending user to login page from an expired session -->
        <navigation-rule>
            <from-view-id>*</from-view-id>
            <navigation-case>
                <from-outcome>gotologin</from-outcome>
                <to-view-id>/login.em</to-view-id>
                <redirect />
            </navigation-case>
        </navigation-rule>
    

    就是这样,只要您在任何页面上都没有会话并且不在登录页面上,您将被带到登录页面。

    享受

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-18
      • 1970-01-01
      • 2010-11-01
      • 2012-09-26
      • 2019-06-27
      • 2016-02-21
      相关资源
      最近更新 更多