Избегайте кнопки возврата в веб-приложении JSF

Я показываю очень важные данные. После того, как пользователь выходит из моего сервера, я не хочу, чтобы другой пользователь мог видеть данные, нажимающие кнопку Назад браузера.

Как мне этого добиться?

2 ответа

Решение

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

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

@WebFilter
public class NoCacheFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

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

        chain.doFilter(req, res);
    }

    // ...
}

(обратите внимание, что этот фильтр пропускает запросы ресурсов JSF, кеширование которых необходимо настроить отдельно)

Чтобы запустить его при каждом запросе JSF, установите следующую аннотацию для класса фильтра, предполагая, что значение <servlet-name> из FacesServlet в вашем веб-приложении web.xml является facesServlet:

@WebFilter(servletNames={"facesServlet"})

Или, чтобы заставить его работать только на определенном шаблоне URL, таком как тот, который соответствует запрещенным страницам, например /app/*, /private/*, /secured/* или около того, установите следующую аннотацию для класса фильтра:

@WebFilter("/app/*")

Вы можете даже выполнить ту же самую работу в фильтре, который проверяет вошедшего в систему пользователя, если он у вас уже есть.

Если вам случится использовать служебную библиотеку JSF OmniFaces, то вы также можете просто взять ее CacheControlFilter, Это также прозрачно учитывает ресурсы JSF.

Смотрите также:

Я также нашел другое хорошее решение.

В лица-config.xml добавить

<lifecycle>
    <phase-listener id="nocache">client.security.CacheControlPhaseListener</phase-listener>
</lifecycle>

И реализовать следующий класс:

package client.security;

import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.servlet.http.HttpServletResponse;

@SuppressWarnings("serial")
public class CacheControlPhaseListener implements PhaseListener
{
    public PhaseId getPhaseId()
    {
        return PhaseId.RENDER_RESPONSE;
    }

    public void afterPhase(PhaseEvent event)        
    {
    }

    public void beforePhase(PhaseEvent event)
    {
       FacesContext facesContext = event.getFacesContext();
       HttpServletResponse response = (HttpServletResponse) facesContext
                .getExternalContext().getResponse();
       response.addHeader("Pragma", "no-cache");
       response.addHeader("Cache-Control", "no-cache");
       // Stronger according to blog comment below that references HTTP spec
       response.addHeader("Cache-Control", "no-store");
       response.addHeader("Cache-Control", "must-revalidate");
       // some date in the past
       response.addHeader("Expires", "Mon, 8 Aug 2006 10:00:00 GMT");
    }
} 
Другие вопросы по тегам