Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disable webpage caching for browser forward/back buttons

I am using following meta tags to prevent browser caching for page:

<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="*" />

Case:

  1. Browser is already opened with page1.
  2. New link is pasted in the browser address bar and now secured page page2 is opened.
  3. User performs action on page2 and is redirected to page3.

When clicking back button on page3, then user gets redirected to page1 (no caching and works fine in this case). When user clicks forward button on page1, then the user is forwarded to the secured page page2. This shouldn't happen.

All of above is tested on IE9.

How is this caused and how can I solve it?

like image 981
Mahmoud Saleh Avatar asked Nov 03 '13 10:11

Mahmoud Saleh


People also ask

Which of the following codes can be used to disable caching on back button of the browser?

header("Pragma: no-cache"); // HTTP 1.0.

How do I disable back forward and refresh functionality in browser?

function disableBackButton() { window. history. forward(); } setTimeout("disableBackButton()", 0);

What is back and forward caching?

Back/forward cache (or bfcache) is a browser optimization that enables instant back and forward navigation. It significantly improves the browsing experience for users—especially those with slower networks or devices.


2 Answers

Your initial attempt with HTML <meta http-equiv> tags specifies the right header values, however, this doesn't work at all because your pages are already served over HTTP. The <meta http-equiv> headers specifies "HTTP-equivalent" headers which are only used when the pages are not served using the HTTP protocol.

For example, when the pages are opened from local disk file system like as if you were doubleclicking a .html file in local disk file system explorer. This would open the .html file via file:// URI instead of http:// URI.

You should be setting those headers on the real HTTP response. You can investigate the headers of the current HTTP response by pressing F12 in Chrome/FireFox>=23/IE>=9 and exploring the HTTP traffic in Network tab. In case of specifically IE9/10, click the Start capturing button, reload the page, select the HTML page, click Go to detailed view button and finally click the Response headers tab. Here's a screenshot of how it look like in IE10 on your current question:

enter image description here

The right way to get those headers to end up there is using HttpServletResponse#setHeader() and friends like setDateHeader(), addHeader(), etc. As you figured, one way is a servlet filter.

See also:

  • Avoid back button on JSF web application
like image 57
BalusC Avatar answered Sep 18 '22 18:09

BalusC


I found out that the best solution is the following filter:

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
}

}

according to the answer in this question:

Redirect to login page when user clicks on back button after logout in JSF

like image 21
Mahmoud Saleh Avatar answered Sep 17 '22 18:09

Mahmoud Saleh