Не удается перенаправить из JSF-фазелистера - PullRequest
0 голосов
/ 20 декабря 2011

Моя проблема похожа на ту, которая здесь , но никак не связана с PrimeFaces.Кроме того, я не смог найти реального решения там.

Я в основном пытаюсь заставить фазселистинер перенаправить на страницу входа в случае, если нет сеанса 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

Что может быть причиной этого?Я делаю это неправильно?

Спасибо!

Ответы [ 2 ]

3 голосов
/ 20 декабря 2011

Это, кажется, происходит во время запроса ajax. Я не уверен в точной причине, трассировка стека, по крайней мере, указывает на возможную ошибку в реализации MyFaces.

По крайней мере, общий подход к дизайну оставляет желать лучшего. Этот вид HTTP-запросов / ответов должен предпочтительно , а не иметь место в PhaseListener. Там это не предназначено для. Вы хотите выполнять эту работу в обычном сервлете Filter вместо.

1 голос
/ 13 марта 2012

Ну, у меня была такая же проблема, как и у вас, но я не решил ее так сложно, как вы. Мои шаги

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

Так как я имею дело с LibrarySessions из Oracle CMSDK, именно поэтому мой тест для сессии выглядит следующим образом. Наиболее важно как-то проверить ваш сеанс и выдать true или false, в зависимости от того, существует сеанс или нет.

3) Настройте прослушиватель в face-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>

И это все, когда у вас нет сеанса на какой-либо странице и вы не находитесь на странице входа, вы будете перенаправлены на страницу входа.

Наслаждайтесь

...