Как переместить страницу пользователя на тайм-аут, когда истекает срок действия сеанса, если пользователь нажмет кнопку "Назад" браузера

Я обрабатываю сеанс в JSF 2.0 с использованием фильтра. Вот код

  @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
        throws IOException, ServletException {

    HttpServletRequest httpServletRequest = (HttpServletRequest) request;
    HttpServletResponse httpServletResponse = (HttpServletResponse) response;

    HttpSession session = httpServletRequest.getSession(false);

    if (session == null) {

        //session timeout check.
        if (httpServletRequest.getRequestedSessionId() != null && !httpServletRequest.isRequestedSessionIdValid()) {

            System.out.println("Session has expired");
            session = httpServletRequest.getSession(true);
            session.setAttribute("logedin", "0");    // public user               
            httpServletResponse.sendRedirect(timeoutPage);

        } else {

            session = httpServletRequest.getSession(true);
            session.setAttribute("logedin", "0");
            filterChain.doFilter(httpServletRequest, httpServletResponse);
        }
    } 
} //end of doFilter()

Но проблема в том, что когда сеанс истекает, и если пользователь нажимает кнопку "Назад", он получает страницу со всем стилем. Есть ли в любом случае, что, когда сессия истекает, и если пользователь нажмет кнопку "Назад назад", то он направит на timeoutPage.

Еще одно, что я также использую компонент Prime Faces на своей странице, например, datatable. Я использую разбиение на страницы. Если сеанс отключен, и я нажимаю на разбиение на страницы, то сообщение об истечении сеанса не отображается. Кажется, что запрос ajax не вызывает фильтр? Как я могу подключить свои события ajax, или вы можете сказать, что данные о постраничной разбивке на страницы до истечения срока действия сеанса?

Спасибо

Ответ 1

когда сеанс истекает, и если пользователь нажимает кнопку "Назад", он получает страницу со всем стилем

Вам нужно сообщить браузеру, что он не кэширует страницы в кеше браузера. Браузер shoud вместо этого отправляет полный запрос на сервер.

Добавьте следующие строки непосредственно перед вызовом filterChain.doFilter().

if (!httpServletRequest.getRequestURI().startsWith(httpServletRequest.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) { // Skip JSF resources (CSS/JS/Images/etc)
    httpServletResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
    httpServletResponse.setHeader("Pragma", "no-cache"); // HTTP 1.0.
    httpServletResponse.setDateHeader("Expires", 0); // Proxies.
}

Если время сеанса сеанса и я нажимаю на разбиение на страницы, то сообщение об окончании сеанса не отображается. Кажется, что запрос ajax не вызывает фильтр?

JSF-запросы ajax ожидают ответы XML с HTTP-статусом 200. Если вы отправляете синхронную переадресацию, тогда будет отправлен ответ HTTP-статуса 302, который будет полностью проигнорирован механизмом ajax JSF. Вместо этого вы должны отправлять обычный ответ HTTP 200 с определенным фрагментом XML, который сообщает JAF ajax-движку выполнить перенаправление. Сделайте это вместо httpServletResponse.sendRedirect(), затем:

if ("partial/ajax".equals(httpServletRequest.getHeader("Faces-Request"))) {
    httpServletResponse.setContentType("text/xml");
    httpServletResponse.getWriter()
        .append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
        .printf("<partial-response><redirect url=\"%s\"></redirect></partial-response>", timeoutPage);
}
else {
    httpServletResponse.sendRedirect(timeoutPage);
}

Обратите внимание: если вы уже находитесь в контексте JSF (например, PhaseListener или SystemEventListener или, возможно, @ManagedBean)), вы можете просто использовать метод ExternalContext#redirect(). Он будет прозрачно обрабатывать синхронные/асинхронные запросы соответственно.