Отключить кеширование веб-страниц для кнопок браузера вперед/назад

Я использую следующие метатеги для предотвращения кеширования браузера для страницы:

<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="-1" />
<meta http-equiv="Vary" content="*" />

Случай:

  • Браузер уже открыт с помощью page1.
  • Новая ссылка вставляется в адресную строку браузера, и теперь открывается защищенная страница page2.
  • Пользователь выполняет действие на page2 и перенаправляется на page3.

При нажатии кнопки page3, пользователь перенаправляется на page1 (без кэширования и в этом случае отлично работает). Когда пользователь нажимает кнопку вперед на page1, пользователь пересылается на защищенную страницу page2. Этого не должно быть.

Все вышеперечисленное проверено на IE9.

Как это вызвано и как я могу его решить?

Ответ 1

Я выяснил, что лучшим решением является следующий фильтр:

import java.io.IOException;
import javax.faces.application.ResourceHandler;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet Filter implementation class NoCacheFilter
 */
  @WebFilter(urlPatterns = {"*.xhtml"})
  public class NoCacheFilter implements Filter {

/**
 * Default constructor. 
 */
public NoCacheFilter() {
    // TODO Auto-generated constructor stub
}

/**
 * @see Filter#destroy()
 */
public void destroy() {
    // TODO Auto-generated method stub
}

/**
 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
 */

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

    // apply no caching for all web pages except resources, you can customize that to be applied for specific pages
    if (!req.getRequestURI().startsWith(req.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) { // Skip JSF resources (CSS/JS/Images/etc)
        res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
        res.setHeader("Pragma", "no-cache"); // HTTP 1.0.
        res.setDateHeader("Expires", 0); // Proxies.
    }

    chain.doFilter(request, response);
}
/**
 * @see Filter#init(FilterConfig)
 */
public void init(FilterConfig fConfig) throws ServletException {
    // TODO Auto-generated method stub
}

}

в соответствии с ответом в этом вопросе:

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

Ответ 2

Ваша первоначальная попытка с тегами HTML <meta http-equiv> указывает значения правого заголовка, однако это не работает вообще, потому что ваши страницы уже через HTTP. Заголовки <meta http-equiv> указывают заголовки "HTTP-эквивалент", которые используются, только когда страницы не обслуживаются с использованием протокола HTTP.

Например, когда страницы открываются из локальной файловой системы на диске, как если бы вы дважды делали файл .html в локальном файловом системном проводнике. Это откроет файл .html через file:// URI вместо http:// URI.

Вы должны установить эти заголовки в ответе HTTP реального. Вы можете исследовать заголовки текущего HTTP-ответа, нажав F12 в Chrome/FireFox >= 23/IE >= 9 и исследовать HTTP-трафик на вкладке Сеть. В случае конкретного IE9/10 нажмите кнопку "Начать захват", перезагрузите страницу, выберите страницу HTML, нажмите "Перейти к подробному представлению" и, наконец, нажмите вкладку "Заголовки ответов". Вот скриншот о том, как он выглядит в IE10 по вашему текущему вопросу:

enter image description here

Правильный способ получить эти заголовки в конечном итоге с помощью HttpServletResponse#setHeader() и друзей вроде setDateHeader(), addHeader(), и т.д. Как вы поняли, одним из способов является фильтр сервлета.

См. также: