Как перенаправить на страницу входа после окончания сеанса?

У меня есть три веб-модуля JSF 2.0, и мне нужно перенаправить на страницу входа в систему по окончании сеанса.

Я пробовал это с помощьюHttpSessionListenerзоветsessionDestroyed() Метод события, но я не могу переслать / перенаправить запрос там. Я думаю, потому что нетHttpServletRequest а такжеHttpServletResponse объекты.

Я также попробовал это с помощьюPhaseListener, но это приводит к «слишком большому количеству перенаправлений» ошибка в веб-браузере.

public class SessionListener implements PhaseListener {

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

    public void beforePhase(PhaseEvent event) {
        if (!FacesContext.getCurrentInstance().isPostback()) {
            try {
                System.out.println("Session Destroyed");
                FacesContext.getCurrentInstance().getExternalContext().redirect("login.jsf");
            }
            catch (Exception e) {
                System.out.println("error" + e);
            }
        }
    }

    public void afterPhase(PhaseEvent event)  {
        try {
            System.out.println("Session Created");
        }
        catch (Exception e) {
            System.out.println("error" + e);
        }
    }

}

Почему эти попытки не работают и как я могу решить их лучше?

Ответы на вопрос(2)

Попробуй использовать

 FacesContext.getCurrentInstance().getApplication().getNavigationHandler().
       handleNavigation(context, null, "LoginForm");

Но обратите внимание, что для этих целей следует использовать Servlet Filter, лучше не делать перенаправлений из PhaseListener, потому что он действительно подвержен ошибкам.

Решение Вопроса

Это & APOS; snot можно отправить перенаправление именно в тот момент, когда сеанс истек. Клиент не отправил ни одного HTTP-запроса в тот момент, который вы могли бы затем перенаправить.

Вы должны просто сохранить существующий механизм аутентификации, который перенаправляет на страницу входа, когда пользователь больше не вошел в систему. В лучшем случае вы можете улучшить его, добавив проверку, перенаправлен ли пользователь на страницу входа.because сеанс истек или просто потому, что он никогда не входил в систему раньше (то есть это новый запрос).

Вы можете проверить это, еслиHttpServletRequest#getRequestedSessionId() не возвращаетсяnull (что означает, что клиент отправил куки-файл сеанса и, следовательно, предполагает, что сеанс все еще действителен) иHttpServletRequest#isRequestedSessionIdValid() возвращаетсяfalse (что означает, что сеанс истек на стороне сервера). Вы можете сделать это в том же фильтре, где вы проверяете вошедшего в систему пользователя (у вас он уже есть, верно? Или вы используете аутентификацию, управляемую контейнером?).

User user = (User) session.getAttribute("user");

if (user == null) {
    String loginURL = request.getContextPath() + "/login.jsf";
    if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) {
        response.sendRedirect(loginURL + "?expired=true");
    } else {
        response.sendRedirect(loginURL);
    }
} else {
    chain.doFilter(request, response);
}

А потом вlogin.xhtml проверка страницы для этого

<h:panelGroup rendered="#{param.expired}">
    <p>You have been redirected to the login page, because your session was expired.</p>
</h:panelGroup>

Ваш подход слушателя фазы, кстати, не имеет никакого смысла. Это действительно отправляет перенаправление наevery single запрос, заставляющий его работать в бесконечном цикле. Фаза представления восстановления не имеет абсолютно никакого отношения к истечению срока действия сеанса.

Ваш ответ на вопрос