无法从 JSF PhaseListener 重定向

发布于 2024-12-22 07:51:31 字数 1293 浏览 0 评论 0原文

我的问题与此处类似,但不是以任何方式涉及 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

什么可能导致这个?我这样做错了吗?

谢谢!

My problem is similar to the one here but doesn't involve PrimeFaces in any way. Also, I couldn't find a real solution there.

I'm basically trying to get the phaselistener to redirect to login page in case there is no JSF session (When, for example, session has timed out)

I'm trying to redirect from within a JSF 2 Phaselistener. To sum up, what I'm doing is this:

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) {
                ...
            }
        }
    }
}

When the redirect code runs I get this exception:

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

What could be causing this? Am I doing this wrong?

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

你在我安 2024-12-29 07:51:31

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

至少,整体设计方法很差。这种 HTTP 请求/响应修改最好发生在PhaseListener中。它不适合在那里。您想在普通的 servlet Filter 中完成此类工作。

This seem to be happening during an ajax request. I'm not sure about the exact cause, the stacktrace at least indicates a possible bug in MyFaces implementation.

At least, the overall design approach is poor. This kind of HTTP request/response modifications should preferably not take place in a PhaseListener. There it is not intended for. You want to do this kind of job in a normal servlet Filter instead.

夜司空 2024-12-29 07:51:31

好吧,我和你有同样的问题,但我没有像你一样以如此复杂的方式解决。我的步骤

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,这就是为什么我的会话测试看起来像这样。最重要的是以某种方式检查您的会话并给出 true 或 false,具体取决于会话是否存在。

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>

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

享受

Well I had the same problem like you but I did not solve in in such a complicated way as you are doing.My steps

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();
  }
}

Sorry for the uncommented code but I guess the code is really easy to understand. Most important thing to note is the afterPhase(..) which checks if I am in the logged in or if I have a session already. If I don´t it creates a navigator and navigates me to the login page

2) Your isLoggedInAgain() should look something like this:

/**
   * 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;
  }

Since I am dealing with LibrarySessions from Oracle CMSDK that is why my test for the session looks like this. Most important is to check your session somehow and give out true or false, depending on if session exist or not.

3) Configure the Listener in 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) Lastly define a navigation rule for the "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>

And that is it, whenever you do not have a session on any page and are not on the login page, you will be carried to the login page.

Enjoy

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文