Our investigations have shown us that not all browsers respect the HTTP cache directives in a uniform manner.
For security reasons we do not want certain pages in our application to be cached, ever, by the web browser. This must work for at least the following browsers:
Our requirement came from a security test. After logging out from our website you could press the back button and view cached pages.
This question is related to
http
caching
https
http-headers
(hey, everyone: please don't just mindlessly copy&paste all headers you can find)
First of all, Back button history is not a cache:
The freshness model (Section 4.2) does not necessarily apply to history mechanisms. That is, a history mechanism can display a previous representation even if it has expired.
In the old HTTP spec the wording was even stronger, explicitly telling browsers to disregard cache directives for back button history.
Back is supposed to go back in time (to the time when the user was logged in). It does not navigate forward to a previously opened URL.
However, in practice, the cache can influence the back button, in very specific circumstances:
Cache-Control: no-store, must-revalidate
(some browsers observe no-store
and some observe must-revalidate
)You never need any of:
<meta>
with cache headers — it doesn't work at all. Totally useless.post-check
/pre-check
— it's IE-only directive that only applies to cachable resources.If you want, you could add:
no-cache
or max-age=0
, which will make resource (URL) "stale" and require browsers to check with the server if there's a newer version (no-store
already implies this even stronger).Expires
with a date in the past for HTTP/1.0 clients (although real HTTP/1.0-only clients are completely non-existent these days).Bonus: The new HTTP caching RFC.
you can use location block for set individual file instead of whole app get caching in IIS
<location path="index.html">
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Cache-Control" value="no-cache" />
</customHeaders>
</httpProtocol>
</system.webServer>
</location>
The headers in the answer provided by BalusC does not prevent Safari 5 (and possibly older versions as well) from displaying content from the browser cache when using the browser's back button. A way to prevent this is to add an empty onunload event handler attribute to the body tag:
<body onunload="">
This hack apparently breaks the back-forward cache in Safari: Is there a cross-browser onload event when clicking the back button?
I just want to point out that if someone wants to prevent caching ONLY dynamic content, adding those additional headers should be made programmatically.
I edited configuration file of my project to append no-cache headers, but that also disabled caching static content, which isn't usually desirable. Modifying response headers in code assures that images and style files will be cached.
This is quite obvious, yet still worth mentioning.
And another caution. Be careful using ClearHeaders method from HttpResponse class. It may give you some bruises if you use it recklessly. Like it gave me.
After redirecting on ActionFilterAttribute event the consequences of clearing all headers are losing all session data and data in TempData storage. It's safer to redirect from an Action or don't clear headers when redirection is taking place.
On second thought I discourage all to use ClearHeaders method. It's better to remove headers separately. And to set Cache-Control header properly I'm using this code:
filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
filterContext.HttpContext.Response.Cache.AppendCacheExtension("no-store, must-revalidate");
As @Kornel stated, what you want is not to deactivate the cache, but to deactivate the history buffer. Different browsers have their own subtle ways to disable the history buffer.
In Chrome (v28.0.1500.95 m) we can do this only by Cache-Control: no-store
.
In FireFox (v23.0.1) any one of these will work:
Cache-Control: no-store
Cache-Control: no-cache
(https only)
Pragma: no-cache
(https only)
Vary: *
(https only)
In Opera (v12.15) we only can do this by Cache-Control: must-revalidate
(https only).
In Safari (v5.1.7, 7534.57.2) any one of these will work:
Cache-Control: no-store
<body onunload="">
in html
Cache-Control: no-store
(https only)
In IE8 (v8.0.6001.18702IC) any one of these will work:
Cache-Control: must-revalidate, max-age=0
Cache-Control: no-cache
Cache-Control: no-store
Cache-Control: must-revalidate
Expires: 0
Cache-Control: must-revalidate
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
(https only)
Vary: *
(https only)
Combining the above gives us this solution which works for Chrome 28, FireFox 23, IE8, Safari 5.1.7, and Opera 12.15: Cache-Control: no-store, must-revalidate
(https only)
Note that https is needed because Opera wouldn't deactivate history buffer for plain http pages. If you really can't get https and you are prepared to ignore Opera, the best you can do is this:
Cache-Control: no-store
<body onunload="">
Below shows the raw logs of my tests:
HTTP:
Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
<body onunload="">
Fail: Opera 12.15
Success: Chrome 28, FireFox 23, IE8, Safari 5.1.7
Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
Vary: *
<body onunload="">
Fail: Opera 12.15
Success: Chrome 28, FireFox 23, IE8, Safari 5.1.7
Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
Fail: Safari 5.1.7, Opera 12.15
Success: Chrome 28, FireFox 23, IE8
Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
Vary: *
Fail: Safari 5.1.7, Opera 12.15
Success: Chrome 28, FireFox 23, IE8
Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
<body onunload="">
Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Success: IE8
Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
Vary: *
<body onunload="">
Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Success: IE8
Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
<body onunload="">
Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Success: IE8
Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
Vary: *
<body onunload="">
Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Success: IE8
Cache-Control: no-store
Fail: Safari 5.1.7, Opera 12.15
Success: Chrome 28, FireFox 23, IE8
Cache-Control: no-store
<body onunload="">
Fail: Opera 12.15
Success: Chrome 28, FireFox 23, IE8, Safari 5.1.7
Cache-Control: no-cache
Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Success: IE8
Vary: *
Fail: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
Success: none
Pragma: no-cache
Fail: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
Success: none
Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
Vary: *
<body onunload="">
Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Success: IE8
Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
<body onunload="">
Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Success: IE8
Cache-Control: must-revalidate, max-age=0
Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Success: IE8
Cache-Control: must-revalidate
Expires: 0
Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Success: IE8
Cache-Control: must-revalidate
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Success: IE8
Cache-Control: private, must-revalidate, proxy-revalidate, s-maxage=0
Pragma: no-cache
Vary: *
<body onunload="">
Fail: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
Success: none
HTTPS:
Cache-Control: private, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
<body onunload="">
Fail: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
Success: none
Cache-Control: private, max-age=0, proxy-revalidate, s-maxage=0
Expires: Sat, 12 Oct 1991 05:00:00 GMT
<body onunload="">
Fail: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
Success: none
Vary: *
Fail: Chrome 28, Safari 5.1.7, Opera 12.15
Success: FireFox 23, IE8
Pragma: no-cache
Fail: Chrome 28, Safari 5.1.7, Opera 12.15
Success: FireFox 23, IE8
Cache-Control: no-cache
Fail: Chrome 28, Safari 5.1.7, Opera 12.15
Success: FireFox 23, IE8
Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
Fail: Chrome 28, Safari 5.1.7, Opera 12.15
Success: FireFox 23, IE8
Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
Fail: Chrome 28, Safari 5.1.7, Opera 12.15
Success: FireFox 23, IE8
Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
Vary: *
Fail: Chrome 28, Safari 5.1.7, Opera 12.15
Success: FireFox 23, IE8
Cache-Control: must-revalidate
Fail: Chrome 28, FireFox 23, IE8, Safari 5.1.7
Success: Opera 12.15
Cache-Control: private, must-revalidate, proxy-revalidate, s-maxage=0
<body onunload="">
Fail: Chrome 28, FireFox 23, IE8, Safari 5.1.7
Success: Opera 12.15
Cache-Control: must-revalidate, max-age=0
Fail: Chrome 28, FireFox 23, Safari 5.1.7
Success: IE8, Opera 12.15
Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
Vary: *
<body onunload="">
Fail: Chrome 28, Safari 5.1.7
Success: FireFox 23, IE8, Opera 12.15
Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
<body onunload="">
Fail: Chrome 28, Safari 5.1.7
Success: FireFox 23, IE8, Opera 12.15
Cache-Control: no-store
Fail: Opera 12.15
Success: Chrome 28, FireFox 23, IE8, Safari 5.1.7
Cache-Control: private, no-cache, no-store, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
<body onunload="">
Fail: Opera 12.15
Success: Chrome 28, FireFox 23, IE8, Safari 5.1.7
Cache-Control: private, no-cache, no-store, max-age=0, proxy-revalidate, s-maxage=0
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
Vary: *
<body onunload="">
Fail: Opera 12.15
Success: Chrome 28, FireFox 23, IE8, Safari 5.1.7
Cache-Control: private, no-cache
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
Vary: *
Fail: Chrome 28, Safari 5.1.7, Opera 12.15
Success: FireFox 23, IE8
Cache-Control: must-revalidate
Expires: 0
Fail: Chrome 28, FireFox 23, Safari 5.1.7,
Success: IE8, Opera 12.15
Cache-Control: must-revalidate
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Fail: Chrome 28, FireFox 23, Safari 5.1.7,
Success: IE8, Opera 12.15
Cache-Control: private, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
<body onunload="">
Fail: Chrome 28, FireFox 23, Safari 5.1.7,
Success: IE8, Opera 12.15
Cache-Control: private, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: Sat, 12 Oct 1991 05:00:00 GMT
<body onunload="">
Fail: Chrome 28, FireFox 23, Safari 5.1.7,
Success: IE8, Opera 12.15
Cache-Control: private, must-revalidate
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
Vary: *
Fail: Chrome 28, Safari 5.1.7
Success: FireFox 23, IE8, Opera 12.15
Cache-Control: no-store, must-revalidate
Fail: none
Success: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
If you're facing download problems with IE6-IE8 over SSL and cache:no-cache header (and similar values) with MS Office files you can use cache:private,no-store header and return file on POST request. It works.
For ASP.NET Core, create a simple middleware class:
public class NoCacheMiddleware
{
private readonly RequestDelegate m_next;
public NoCacheMiddleware( RequestDelegate next )
{
m_next = next;
}
public async Task Invoke( HttpContext httpContext )
{
httpContext.Response.OnStarting( ( state ) =>
{
// ref: http://stackoverflow.com/questions/49547/making-sure-a-web-page-is-not-cached-across-all-browsers
httpContext.Response.Headers.Append( "Cache-Control", "no-cache, no-store, must-revalidate" );
httpContext.Response.Headers.Append( "Pragma", "no-cache" );
httpContext.Response.Headers.Append( "Expires", "0" );
return Task.FromResult( 0 );
}, null );
await m_next.Invoke( httpContext );
}
}
then register it with Startup.cs
app.UseMiddleware<NoCacheMiddleware>();
Make sure you add this somewhere after
app.UseStaticFiles();
The PHP documentation for the header function has a rather complete example (contributed by a third party):
header('Pragma: public');
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
header('Last-Modified: '.gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate'); // HTTP/1.1
header('Cache-Control: pre-check=0, post-check=0, max-age=0', false); // HTTP/1.1
header ("Pragma: no-cache");
header("Expires: 0", false);
The RFC for HTTP 1.1 says the proper method is to add an HTTP Header for:
Cache-Control: no-cache
Older browsers may ignore this if they are not properly compliant to HTTP 1.1. For those you can try the header:
Pragma: no-cache
This is also supposed to work for HTTP 1.1 browsers.
I found that all of the answers on this page still had problems. In particular, I noticed that none of them would stop IE8 from using a cached version of the page when you accessed it by hitting the back button.
After much research and testing, I found that the only two headers I really needed were:
Cache-Control: no-store
Vary: *
For an explanation of the Vary header, check out http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.6
On IE6-8, FF1.5-3.5, Chrome 2-3, Safari 4, and Opera 9-10, these headers caused the page to be requested from the server when you click on a link to the page, or put the URL directly in the address bar. That covers about 99% of all browsers in use as of Jan '10.
On IE6, and Opera 9-10, hitting the back button still caused the cached version to be loaded. On all other browsers I tested, they did fetch a fresh version from the server. So far, I haven't found any set of headers that will cause those browsers to not return cached versions of pages when you hit the back button.
Update: After writing this answer, I realized that our web server is identifying itself as an HTTP 1.0 server. The headers I've listed are the correct ones in order for responses from an HTTP 1.0 server to not be cached by browsers. For an HTTP 1.1 server, look at BalusC's answer.
Not sure if my answer sounds simple and stupid, and perhaps it has already been known to you since long time ago, but since preventing someone from using browser back button to view your historical pages is one of your goals, you can use:
window.location.replace("https://www.example.com/page-not-to-be-viewed-in-browser-history-back-button.html");
Of course, this may not be possible to be implemented across the entire site, but at least for some critical pages, you can do that. Hope this helps.
The use of the pragma header in the response is a wives tale. RFC2616 only defines it as a request header
DISCLAIMER: I strongly suggest reading @BalusC's answer. After reading the following caching tutorial: http://www.mnot.net/cache_docs/ (I recommend you read it, too), I believe it to be correct. However, for historical reasons (and because I have tested it myself), I will include my original answer below:
I tried the 'accepted' answer for PHP, which did not work for me. Then I did a little research, found a slight variant, tested it, and it worked. Here it is:
header('Cache-Control: no-store, private, no-cache, must-revalidate'); // HTTP/1.1
header('Cache-Control: pre-check=0, post-check=0, max-age=0, max-stale = 0', false); // HTTP/1.1
header('Pragma: public');
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT'); // Date in the past
header('Expires: 0', false);
header('Last-Modified: '.gmdate('D, d M Y H:i:s') . ' GMT');
header ('Pragma: no-cache');
That should work. The problem was that when setting the same part of the header twice, if the false
is not sent as the second argument to the header function, header function will simply overwrite the previous header()
call. So, when setting the Cache-Control
, for example if one does not want to put all the arguments in one header()
function call, he must do something like this:
header('Cache-Control: this');
header('Cache-Control: and, this', false);
See more complete documentation here.
//In .net MVC
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public ActionResult FareListInfo(long id)
{
}
// In .net webform
<%@ OutputCache NoStore="true" Duration="0" VaryByParam="*" %>
i have solved in this way.
2 considerations:
1) the server side events are not fired on back click, instead of javascript.
2) i have 2 javascript to read/write cookies
function setCookie(name, value, days)
{
var expires = "";
if (days)
{
var date = new Date();
date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
expires = "; expires=" + date.toUTCString();
}
document.cookie = name + "=" + (value || "") + expires + "; path=/";
}
function getCookie(name)
{
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for (var i = ca.length - 1; i >= 0; i--)
{
var c = ca[i];
while (c.charAt(0) == ' ')
{
c = c.substring(1, c.length);
}
if (c.indexOf(nameEQ) == 0)
{
return c.substring(nameEQ.length, c.length);
}
}
return null;
}
in my Page_Load i inserted this: (this is NOT fired on back click)
protected void Page_Load(object sender, EventArgs e)
{
Page.RegisterClientScriptBlock("", "<script>setCookie('" + Session.SessionID + "', '" + Login + "', '100');</script>");
}
where 'Login' is my id value that is -1 after logout (you could use something else, a boolean for example).
then in my page i added this: (this IS fired on back click)
<script type="text/javascript">
if (getCookie('<%= Session.SessionID %>') < 0)
{
if (history.length > 0)
{
history.go(+1);
}
}
</script>
nothing else.
with this solution back click is enable on every page and disable only after logout on each page on the same browser.
I've had best and most consistent results across all browsers by setting Pragma: no-cache
The accepted answer does not appear to work for IIS7+, going by the large number of questions about cache headers not being sent in II7:
And so on
The accepted answer is correct in which headers must be set, but not in how they must be set. This way works with IIS7:
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.AppendCacheExtension("no-store, must-revalidate");
Response.AppendHeader("Pragma", "no-cache");
Response.AppendHeader("Expires", "-1");
The first line sets Cache-control
to no-cache
, and the second line adds the other attributes no-store, must-revalidate
Also, just for good measure, make sure you reset the ExpiresDefault
in your .htaccess
file if you're using that to enable caching.
ExpiresDefault "access plus 0 seconds"
Afterwards, you can use ExpiresByType
to set specific values for the files you want to cache:
ExpiresByType image/x-icon "access plus 3 month"
This may also come in handy if your dynamic files e.g. php, etc. are being cached by the browser, and you can't figure out why. Check ExpiresDefault
.
in my case i fix the problem in chrome with this
<form id="form1" runat="server" autocomplete="off">
where i need to clear the content of a previus form data when the users click button back for security reasons
To complete BalusC -> ANSWER If you are using perl you can use CGI to add HTTP headers.
Using Perl:
Use CGI;
sub set_new_query() {
binmode STDOUT, ":utf8";
die if defined $query;
$query = CGI->new();
print $query->header(
-expires => 'Sat, 26 Jul 1997 05:00:00 GMT',
-Pragma => 'no-cache',
-Cache_Control => join(', ', qw(
private
no-cache
no-store
must-revalidate
max-age=0
pre-check=0
post-check=0
))
);
}
Using apache httpd.conf
<FilesMatch "\.(html|htm|js|css|pl)$">
FileETag None
<ifModule mod_headers.c>
Header unset ETag
Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
</ifModule>
Note: When I tried to use the html META, browsers ignored them and cached the page.
Setting the modified http header to some date in 1995 usually does the trick.
Here's an example:
Expires: Wed, 15 Nov 1995 04:58:08 GMT Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT Cache-Control: no-cache, must-revalidate
I had no luck with <head><meta>
elements. Adding HTTP cache related parameters directly (outside of the HTML doc) does indeed work for me.
Sample code in Python using web.py web.header
calls follows. I purposefully redacted my personal irrelevant utility code.
import web import sys import PERSONAL-UTILITIES myname = "main.py" urls = ( '/', 'main_class' ) main = web.application(urls, globals()) render = web.template.render("templates/", base="layout", cache=False) class main_class(object): def GET(self): web.header("Cache-control","no-cache, no-store, must-revalidate") web.header("Pragma", "no-cache") web.header("Expires", "0") return render.main_form() def POST(self): msg = "POSTed:" form = web.input(function = None) web.header("Cache-control","no-cache, no-store, must-revalidate") web.header("Pragma", "no-cache") web.header("Expires", "0") return render.index_laid_out(greeting = msg + form.function) if __name__ == "__main__": nargs = len(sys.argv) # Ensure that there are enough arguments after python program name if nargs != 2: LOG-AND-DIE("%s: Command line error, nargs=%s, should be 2", myname, nargs) # Make sure that the TCP port number is numeric try: tcp_port = int(sys.argv[1]) except Exception as e: LOG-AND-DIE ("%s: tcp_port = int(%s) failed (not an integer)", myname, sys.argv[1]) # All is well! JUST-LOG("%s: Running on port %d", myname, tcp_port) web.httpserver.runsimple(main.wsgifunc(), ("localhost", tcp_port)) main.run()
These directives does not mitigate any security risk. They are really intended to force UA's to refresh volatile information, not keep UA's from being retaining information. See this similar question. At the very least, there is no guarantee that any routers, proxies, etc. will not ignore the caching directives as well.
On a more positive note, policies regarding physical access to computers, software installation, and the like will put you miles ahead of most firms in terms of security. If the consumers of this information are members of the public, the only thing you can really do is help them understand that once the information hits their machine, that machine is their responsibility, not yours.
I found the web.config route useful (tried to add it to the answer but doesn't seem to have been accepted so posting here)
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Cache-Control" value="no-cache, no-store, must-revalidate" />
<!-- HTTP 1.1. -->
<add name="Pragma" value="no-cache" />
<!-- HTTP 1.0. -->
<add name="Expires" value="0" />
<!-- Proxies. -->
</customHeaders>
</httpProtocol>
</system.webServer>
And here is the express / node.js way of doing the same:
app.use(function(req, res, next) {
res.setHeader('Cache-Control', 'no-cache, no-store, must-revalidate');
res.setHeader('Pragma', 'no-cache');
res.setHeader('Expires', '0');
next();
});
See this link to a Case Study on Caching:
http://securityevaluators.com/knowledge/case_studies/caching/
Summary, according to the article, only Cache-Control: no-store
works on Chrome, Firefox and IE. IE accepts other controls, but Chrome and Firefox do not. The link is a good read complete with the history of caching and documenting proof of concept.
There's a bug in IE6
Content with "Content-Encoding: gzip" is always cached even if you use "Cache-Control: no-cache".
http://support.microsoft.com/kb/321722
You can disable gzip compression for IE6 users (check the user agent for "MSIE 6")
After a bit of research we came up with the following list of headers that seemed to cover most browsers:
In ASP.NET we added these using the following snippet:
Response.ClearHeaders();
Response.AppendHeader("Cache-Control", "no-cache"); //HTTP 1.1
Response.AppendHeader("Cache-Control", "private"); // HTTP 1.1
Response.AppendHeader("Cache-Control", "no-store"); // HTTP 1.1
Response.AppendHeader("Cache-Control", "must-revalidate"); // HTTP 1.1
Response.AppendHeader("Cache-Control", "max-stale=0"); // HTTP 1.1
Response.AppendHeader("Cache-Control", "post-check=0"); // HTTP 1.1
Response.AppendHeader("Cache-Control", "pre-check=0"); // HTTP 1.1
Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0
Response.AppendHeader("Expires", "Sat, 26 Jul 1997 05:00:00 GMT"); // HTTP 1.0
Found from: http://forums.asp.net/t/1013531.aspx
In addition to the headers consider serving your page via https. Many browsers will not cache https by default.
Source: Stackoverflow.com