http - htaccess - ¿Cómo controlar el almacenamiento en caché de páginas web, en todos los navegadores?
no cache html (26)
Nuestras investigaciones nos han demostrado que no todos los navegadores respetan las directivas de caché http de manera uniforme.
Por razones de seguridad, no queremos que ciertas páginas de nuestra aplicación sean almacenadas en caché, nunca, por el navegador web. Esto debe funcionar para al menos los siguientes navegadores:
- Internet Explorer 6+
- Firefox 1.5 o superior
- Safari 3+
- Opera 9+
- Cromo
Nuestro requisito vino de una prueba de seguridad. Después de cerrar sesión en nuestro sitio web, puede presionar el botón Atrás y ver las páginas en caché.
Introducción
El conjunto mínimo correcto de encabezados que funciona en todos los clientes (y proxies) mencionados:
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0
El Cache-Control
es por la especificación de HTTP 1.1 para clientes y proxies (y es implícitamente requerido por algunos clientes al lado de Expires
). El Pragma
es según la especificación HTTP 1.0 para clientes prehistóricos. Expires
es según la especificación HTTP 1.0 y 1.1 para clientes y proxies. En HTTP 1.1, el Cache-Control
tiene prioridad sobre Expires
, por lo que es solo para proxies HTTP 1.0.
Si no te importa IE6 y su almacenamiento en caché roto al servir páginas a través de HTTPS solo con no-store
, entonces puedes omitir Cache-Control: no-cache
.
Cache-Control: no-store, must-revalidate
Pragma: no-cache
Expires: 0
Si no le importan los clientes IE6 ni HTTP 1.0 (HTTP 1.1 se introdujo en 1997), entonces podría omitir Pragma
.
Cache-Control: no-store, must-revalidate
Expires: 0
Si a usted tampoco le importan los proxies HTTP 1.0, puede omitir Expires
.
Cache-Control: no-store, must-revalidate
Por otro lado, si el servidor incluye automáticamente un encabezado de Date
válido, teóricamente también podrías omitir Cache-Control
y depender solo de Expires
.
Date: Wed, 24 Aug 2016 18:32:02 GMT
Expires: 0
Pero eso puede fallar si, por ejemplo, el usuario final manipula la fecha del sistema operativo y el software del cliente depende de ella.
Otros parámetros de Cache-Control
como max-age
son irrelevantes si se especifican los parámetros de Cache-Control
antes mencionados. El encabezado Last-Modified
que se incluye en la mayoría de las demás respuestas aquí solo es interesante si realmente desea almacenar en caché la solicitud, por lo que no necesita especificarla en absoluto.
¿Cómo configurarlo?
Utilizando PHP:
header("Cache-Control: no-cache, no-store, must-revalidate"); // HTTP 1.1.
header("Pragma: no-cache"); // HTTP 1.0.
header("Expires: 0"); // Proxies.
Utilizando Java Servlet, o Node.js:
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setHeader("Expires", "0"); // Proxies.
Utilizando ASP.NET-MVC
Response.Cache.SetCacheability(HttpCacheability.NoCache); // HTTP 1.1.
Response.Cache.AppendCacheExtension("no-store, must-revalidate");
Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0.
Response.AppendHeader("Expires", "0"); // Proxies.
Usando la API web de ASP.NET:
// `response` is an instance of System.Net.Http.HttpResponseMessage
response.Headers.CacheControl = new CacheControlHeaderValue
{
NoCache = true,
NoStore = true,
MustRevalidate = true
};
response.Headers.Pragma.ParseAdd("no-cache");
// We can''t use `response.Content.Headers.Expires` directly
// since it allows only `DateTimeOffset?` values.
response.Content?.Headers.TryAddWithoutValidation("Expires", 0.ToString());
Utilizando ASP.NET:
Response.AppendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
Response.AppendHeader("Pragma", "no-cache"); // HTTP 1.0.
Response.AppendHeader("Expires", "0"); // Proxies.
Utilizando ASP:
Response.addHeader "Cache-Control", "no-cache, no-store, must-revalidate" '' HTTP 1.1.
Response.addHeader "Pragma", "no-cache" '' HTTP 1.0.
Response.addHeader "Expires", "0" '' Proxies.
Usando Ruby on Rails, o Python / Flask:
response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate" # HTTP 1.1.
response.headers["Pragma"] = "no-cache" # HTTP 1.0.
response.headers["Expires"] = "0" # Proxies.
Usando Python / Django:
response["Cache-Control"] = "no-cache, no-store, must-revalidate" # HTTP 1.1.
response["Pragma"] = "no-cache" # HTTP 1.0.
response["Expires"] = "0" # Proxies.
Usando Python / Pyramid:
request.response.headerlist.extend(
(
(''Cache-Control'', ''no-cache, no-store, must-revalidate''),
(''Pragma'', ''no-cache''),
(''Expires'', ''0'')
)
)
Utilizando Google Go:
responseWriter.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") // HTTP 1.1.
responseWriter.Header().Set("Pragma", "no-cache") // HTTP 1.0.
responseWriter.Header().Set("Expires", "0") // Proxies.
Usando el archivo .htaccess
Apache:
<IfModule mod_headers.c>
Header set Cache-Control "no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires 0
</IfModule>
Utilizando HTML4:
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
HTML etiquetas meta vs encabezados de respuesta HTTP
Es importante saber que cuando se sirve una página HTML a través de una conexión HTTP, y un encabezado está presente tanto en los encabezados de respuesta HTTP como en las etiquetas HTML <meta http-equiv>
, entonces el que está especificado en el encabezado de respuesta HTTP tendrá prioridad. sobre la metaetiqueta HTML. La metaetiqueta HTML solo se utilizará cuando la página se vea desde el sistema de archivos del disco local a través de un file://
URL. Véase también el capítulo 5.2.2 de las especificaciones HTML de W3 . Tenga cuidado con esto cuando no los especifique programáticamente, porque el servidor web puede incluir algunos valores predeterminados.
En general, es mejor que no especifiques las metaetiquetas HTML para evitar confusiones por parte de los principiantes, y confíes en los encabezados de respuesta HTTP difíciles. Además, específicamente esas etiquetas <meta http-equiv>
no son válidas en HTML5. Solo se permiten los valores http-equiv
listados en la especificación HTML5 .
Verificación de los encabezados de respuesta HTTP reales
Para verificar el uno y el otro, puede verlos / depurarlos en el monitor de tráfico HTTP del conjunto de herramientas para desarrolladores del navegador web. Puede llegar allí presionando F12 en Chrome / Firefox23 + / IE9 +, y luego abriendo el panel de pestañas "Red" o "Red", y luego haciendo clic en la solicitud HTTP de interés para descubrir todos los detalles sobre la solicitud y respuesta HTTP. La captura de pantalla de abajo es de Chrome:
Quiero establecer esos encabezados en descargas de archivos también
En primer lugar, esta pregunta y respuesta está dirigida a "páginas web" (páginas HTML), no a "descargas de archivos" (PDF, zip, Excel, etc.). Será mejor que los guarde en caché y haga uso de algún identificador de versión de archivo en algún lugar de la ruta URI o cadena de consulta para forzar una nueva descarga en un archivo modificado. De todos modos, cuando aplique esos encabezados de no caché en las descargas de archivos, tenga cuidado con el error IE7 / 8 cuando sirva una descarga de archivos a través de HTTPS en lugar de HTTP. Para más detalles, vea IE no puede descargar foo.jsf. IE no pudo abrir este sitio de internet. El sitio solicitado no está disponible o no se puede encontrar .
(hey, todos: no copien y peguen sin pensar todos los encabezados que puedan encontrar)
En primer lugar, el historial del botón Atrás no es un caché :
El modelo de frescura (Sección 4.2) no se aplica necesariamente a los mecanismos históricos. Es decir, un mecanismo de historial puede mostrar una representación previa incluso si ha caducado.
En la antigua especificación de HTTP, la redacción era aún más fuerte, e indicaba explícitamente a los navegadores que ignoraran las directivas de caché para el historial del botón Atrás.
Se supone que Atrás debe retroceder en el tiempo (hasta el momento en que el usuario inició sesión). No navega hacia adelante a una URL abierta previamente.
Sin embargo, en la práctica, el caché puede influir en el botón de retroceso, en circunstancias muy específicas:
- La página debe entregarse a través de HTTPS , de lo contrario este almacenamiento de caché no será confiable. Además, si no está utilizando HTTPS, su página es vulnerable al robo de acceso de muchas otras formas.
- Debe enviar
Cache-Control: no-store, must-revalidate
(algunos navegadores observanno-store
y otrosmust-revalidate
)
Nunca necesitas nada de:
-
<meta>
con encabezados de caché - no funciona en absoluto. Totalmente inútil. -
post-check
/pre-check
: es una directiva solo para IE que solo se aplica a los recursos en caché . - Enviando el mismo encabezado dos veces o en docenas de partes. Algunos fragmentos de código PHP por ahí reemplazan los encabezados anteriores, lo que hace que solo se envíe el último.
Si quieres, puedes añadir:
-
no-cache
omax-age=0
, lo que hará que el recurso (URL) esté "obsoleto" y requerirá que los navegadores verifiquen con el servidor si hay una versión más nueva (no-store
ya implica que esto es aún más sólido). -
Expires
con una fecha en el pasado para clientes HTTP / 1.0 (aunque en la actualidad los clientes reales solo con HTTP / 1.0 son totalmente inexistentes).
Bonus: El nuevo HTTP de caché RFC .
Como lo indicó porneL, lo que desea es no desactivar el caché, sino desactivar el búfer de historial. Los diferentes navegadores tienen sus propias formas sutiles de deshabilitar el búfer de historial.
En Chrome (v28.0.1500.95 m) solo podemos hacerlo mediante Cache-Control: no-store
.
En FireFox (v23.0.1) cualquiera de estos funcionará:
Cache-Control: no-store
Cache-Control: no-cache
(solo https)Pragma: no-cache
(solo https)Vary: *
(solo https)
En Opera (v12.15) solo podemos hacer esto mediante Cache-Control: must-revalidate
(solo https).
En Safari (v5.1.7, 7534.57.2) cualquiera de estos funcionará:
Cache-Control: no-store
<body onunload="">
en htmlCache-Control: no-store
(solo https)
En IE8 (v8.0.6001.18702IC) cualquiera de estos funcionará:
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
(solo https)Vary: *
(solo https)
La combinación de lo anterior nos da esta solución que funciona para Chrome 28, FireFox 23, IE8, Safari 5.1.7 y Opera 12.15: Cache-Control: no-store, must-revalidate
(solo https)
Tenga en cuenta que https es necesario porque Opera no desactivará el búfer de historial para páginas http sin formato. Si realmente no puede obtener https y está preparado para ignorar Opera, lo mejor que puede hacer es esto:
Cache-Control: no-store
<body onunload="">
A continuación se muestran los registros en bruto de mis pruebas:
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="">
Falla: la ópera 12.15
Éxito: Chrome 28, FireFox 23, IE8, Safari 5.1.7Cache-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="">
Falla: la ópera 12.15
Éxito: Chrome 28, FireFox 23, IE8, Safari 5.1.7Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
Falla: Safari 5.1.7, Opera 12.15
Éxito: Chrome 28, FireFox 23, IE8Cache-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: *
Falla: Safari 5.1.7, Opera 12.15
Éxito: Chrome 28, FireFox 23, IE8Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
<body onunload="">
Falla: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Éxito: IE8Cache-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="">
Falla: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Éxito: IE8Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
<body onunload="">
Falla: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Éxito: IE8Cache-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="">
Falla: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Éxito: IE8Cache-Control: no-store
Falla: Safari 5.1.7, Opera 12.15
Éxito: Chrome 28, FireFox 23, IE8Cache-Control: no-store
<body onunload="">
Falla: la ópera 12.15
Éxito: Chrome 28, FireFox 23, IE8, Safari 5.1.7Cache-Control: no-cache
Falla: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Éxito: IE8Vary: *
Falla: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
Éxito: ningunoPragma: no-cache
Falla: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
Éxito: ningunoCache-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="">
Falla: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Éxito: IE8Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
<body onunload="">
Falla: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Éxito: IE8Cache-Control: must-revalidate, max-age=0
Falla: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Éxito: IE8Cache-Control: must-revalidate
Expires: 0
Falla: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Éxito: IE8Cache-Control: must-revalidate
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Falla: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Éxito: IE8Cache-Control: private, must-revalidate, proxy-revalidate, s-maxage=0
Pragma: no-cache
Vary: *
<body onunload="">
Falla: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
Éxito: ninguno
HTTPS:
Cache-Control: private, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
<body onunload="">
Falla: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
Éxito: ningunoCache-Control: private, max-age=0, proxy-revalidate, s-maxage=0
Expires: Sat, 12 Oct 1991 05:00:00 GMT
<body onunload="">
Falla: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
Éxito: ningunoVary: *
Falla: Chrome 28, Safari 5.1.7, Opera 12.15
Éxito: FireFox 23, IE8Pragma: no-cache
Falla: Chrome 28, Safari 5.1.7, Opera 12.15
Éxito: FireFox 23, IE8Cache-Control: no-cache
Falla: Chrome 28, Safari 5.1.7, Opera 12.15
Éxito: FireFox 23, IE8Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
Falla: Chrome 28, Safari 5.1.7, Opera 12.15
Éxito: FireFox 23, IE8Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
Falla: Chrome 28, Safari 5.1.7, Opera 12.15
Éxito: FireFox 23, IE8Cache-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: *
Falla: Chrome 28, Safari 5.1.7, Opera 12.15
Éxito: FireFox 23, IE8Cache-Control: must-revalidate
Falla: Chrome 28, FireFox 23, IE8, Safari 5.1.7
Éxito: la ópera 12.15Cache-Control: private, must-revalidate, proxy-revalidate, s-maxage=0
<body onunload="">
Falla: Chrome 28, FireFox 23, IE8, Safari 5.1.7
Éxito: la ópera 12.15Cache-Control: must-revalidate, max-age=0
Falla: Chrome 28, FireFox 23, Safari 5.1.7
Éxito: IE8, Opera 12.15Cache-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="">
Falla: Chrome 28, Safari 5.1.7
Éxito: FireFox 23, IE8, Opera 12.15Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
<body onunload="">
Falla: Chrome 28, Safari 5.1.7
Éxito: FireFox 23, IE8, Opera 12.15Cache-Control: no-store
Falla: la ópera 12.15
Éxito: Chrome 28, FireFox 23, IE8, Safari 5.1.7Cache-Control: private, no-cache, no-store, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
<body onunload="">
Falla: la ópera 12.15
Éxito: Chrome 28, FireFox 23, IE8, Safari 5.1.7Cache-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="">
Falla: la ópera 12.15
Éxito: Chrome 28, FireFox 23, IE8, Safari 5.1.7Cache-Control: private, no-cache
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
Vary: *
Falla: Chrome 28, Safari 5.1.7, Opera 12.15
Éxito: FireFox 23, IE8Cache-Control: must-revalidate
Expires: 0
Falla: Chrome 28, FireFox 23, Safari 5.1.7,
Éxito: IE8, Opera 12.15Cache-Control: must-revalidate
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Falla: Chrome 28, FireFox 23, Safari 5.1.7,
Éxito: IE8, Opera 12.15Cache-Control: private, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
<body onunload="">
Falla: Chrome 28, FireFox 23, Safari 5.1.7,
Éxito: IE8, Opera 12.15Cache-Control: private, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: Sat, 12 Oct 1991 05:00:00 GMT
<body onunload="">
Falla: Chrome 28, FireFox 23, Safari 5.1.7,
Éxito: IE8, Opera 12.15Cache-Control: private, must-revalidate
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
Vary: *
Falla: Chrome 28, Safari 5.1.7
Éxito: FireFox 23, IE8, Opera 12.15Cache-Control: no-store, must-revalidate
Fallo: ninguno
Éxito: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
DESCARGO DE RESPONSABILIDAD: Sugiero encarecidamente leer la respuesta de @BalusC Después de leer el siguiente tutorial de almacenamiento en caché: http://www.mnot.net/cache_docs/ (También te recomiendo que lo leas), creo que es correcto. Sin embargo, por razones históricas (y porque lo he probado yo mismo), incluiré mi respuesta original a continuación:
Probé la respuesta ''aceptada'' para PHP, que no funcionó para mí. Luego hice una pequeña investigación, encontré una variante ligera, la probé y funcionó. Aquí está:
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'');
Eso debería funcionar. El problema fue que cuando se configura la misma parte del encabezado dos veces, si el false
no se envía como segundo argumento a la función de encabezado, la función de encabezado simplemente sobrescribirá la llamada del header()
anterior. Entonces, al configurar el Cache-Control
, por ejemplo, si uno no quiere poner todos los argumentos en una llamada de función de header()
, debe hacer algo como esto:
header(''Cache-Control: this'');
header(''Cache-Control: and, this'', false);
Ver más documentación completa here .
Después de un poco de investigación, encontramos la siguiente lista de encabezados que parecían cubrir la mayoría de los navegadores:
- Expires lunes 26 de julio de 1997 05:00:00 GMT
- Cache-Control w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.1 : w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.1 , privado, must-revalidate , max-stale = 0, post-check = 0, pre-check = 0 no-store
- Pragma : no-caché
En ASP.NET los agregamos usando el siguiente fragmento de código:
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", "Mon, 26 Jul 1997 05:00:00 GMT"); // HTTP 1.0
Encontrado en: http://forums.asp.net/t/1013531.aspx
El RFC para HTTP 1.1 dice que el método correcto es agregar un encabezado HTTP para:
Control de caché: no-caché
Los navegadores más antiguos pueden ignorar esto si no cumplen correctamente con HTTP 1.1. Para aquellos puedes probar el encabezado:
Pragma: no-caché
También se supone que esto funciona para los navegadores HTTP 1.1.
El uso del encabezado pragma en la respuesta es un cuento de esposas. RFC2616 solo lo define como un encabezado de solicitud
Encontré la ruta web.config útil (intenté agregarla a la respuesta pero no parece haber sido aceptada, así que publique aquí)
<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>
Y aquí está la forma expresa / node.js de hacer lo mismo:
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();
});
Encontré que todas las respuestas en esta página todavía tenían problemas. En particular, noté que ninguno de ellos detendría a IE8 de usar una versión en caché de la página cuando accedas a ella presionando el botón Atrás.
Después de mucha investigación y pruebas, descubrí que las dos únicas cabeceras que realmente necesitaba eran:
Cache-Control: no-store
Variar: *
Para obtener una explicación del encabezado de Vary, consulte http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.6
En IE6-8, FF1.5-3.5, Chrome 2-3, Safari 4 y Opera 9-10, estos encabezados hicieron que la página se solicitara desde el servidor al hacer clic en un enlace a la página, o poner la URL directamente en la barra de direcciones. Eso cubre aproximadamente el 99% de todos los navegadores en uso a partir del 10 de enero.
En IE6, y Opera 9-10, al presionar el botón Atrás todavía se cargaba la versión en caché. En todos los demás navegadores que probé, obtuvieron una versión nueva del servidor. Hasta ahora, no he encontrado ningún conjunto de encabezados que haga que esos navegadores no devuelvan versiones de páginas en caché cuando presionas el botón Atrás.
Actualización: Después de escribir esta respuesta, me di cuenta de que nuestro servidor web se está identificando como un servidor HTTP 1.0. Los encabezados que he enumerado son los correctos para que las respuestas de un servidor HTTP 1.0 no sean almacenadas en caché por los navegadores. Para un servidor HTTP 1.1, mira la answer de BalusC.
Establecer el encabezado http modificado en alguna fecha en 1995 generalmente funciona.
Aquí hay un ejemplo:
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
Estas directivas no mitigan ningún riesgo de seguridad. Realmente tienen la intención de obligar a los UA a actualizar la información volátil, no a evitar que los UA retengan información. Vea esta pregunta similar . Como mínimo, no hay garantía de que ningún enrutador, proxy, etc. no ignorará las directivas de almacenamiento en caché también.
En una nota más positiva, las políticas con respecto al acceso físico a las computadoras, la instalación de software y similares le pondrán a la vanguardia en términos de seguridad. Si los consumidores de esta información son miembros del público, lo único que realmente puede hacer es ayudarlos a comprender que una vez que la información llega a su máquina, esa máquina es su responsabilidad, no la suya.
Hay un error en IE6
El contenido con "Content-Encoding: gzip" siempre se almacena en caché incluso si usa "Cache-Control: no-cache".
http://support.microsoft.com/kb/321722
Puede deshabilitar la compresión gzip para los usuarios de IE6 (consulte el agente de usuario para "MSIE 6")
He obtenido mejores y más consistentes resultados en todos los navegadores al configurar Pragma: no-cache
La documentación de PHP para la función de encabezado tiene un ejemplo bastante completo (contribuido por un tercero):
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);
La respuesta aceptada no parece funcionar para IIS7 +, debido a la gran cantidad de preguntas sobre los encabezados de caché que no se enviaron en II7:
- Algo está forzando que las respuestas tengan control de caché: privado en IIS7
- IIS7: configuración de caché no funciona ... ¿por qué?
- Los encabezados de almacenamiento en caché del cliente MVC de IIS7 + ASP.NET no funcionan
- Establecer el control de caché para las páginas aspx
- Control de caché: no-store, must-revalidate no enviado al navegador del cliente en IIS7 + ASP.NET MVC
Y así
La respuesta aceptada es correcta en qué encabezados se deben establecer, pero no en cómo se deben establecer. De esta manera funciona con IIS7:
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.AppendCacheExtension("no-store, must-revalidate");
Response.AppendHeader("Pragma", "no-cache");
Response.AppendHeader("Expires", "-1");
La primera línea se establece Cache-control
en no-cache
, y la segunda línea agrega los otros atributosno-store, must-revalidate
Los encabezados en la respuesta proporcionada por BalusC no impiden que Safari 5 (y posiblemente también las versiones más antiguas) muestren contenido desde la memoria caché del navegador cuando se usa el botón de retroceso del navegador. Una forma de evitar esto es agregar un atributo de controlador de eventos onunload vacío a la etiqueta del cuerpo:
<body onunload="">
Este truco aparentemente rompe el caché de avance en Safari: ¿hay un evento de carga de navegador cruzado al hacer clic en el botón Atrás?
Para ASP.NET Core, cree una clase de middleware simple:
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://.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 );
}
}
luego registralo con Startup.cs
app.UseMiddleware<NoCacheMiddleware>();
Asegúrate de agregar esto en algún lugar después de
app.UseStaticFiles();
Si tiene problemas de descarga con IE6-IE8 sobre SSL y caché: encabezado sin caché (y valores similares) con archivos de MS Office, puede usar caché: privado, encabezado sin almacén y archivo de retorno en la solicitud POST. Funciona.
en mi caso soluciono el problema en chrome con esto
<form id="form1" runat="server" autocomplete="off">
donde necesito borrar el contenido de los datos de un formulario anterior cuando los usuarios hacen clic en el botón de nuevo por razones de seguridad
Solo quiero señalar que si alguien quiere evitar el almacenamiento en caché SOLAMENTE de contenido dinámico, agregar esos encabezados adicionales debe hacerse mediante programación.
Edité el archivo de configuración de mi proyecto para agregar encabezados sin caché, pero eso también deshabilitó el almacenamiento en caché de contenido estático, lo que no suele ser deseable. La modificación de los encabezados de respuesta en el código garantiza que las imágenes y los archivos de estilo se almacenarán en caché.
Esto es bastante obvio, pero vale la pena mencionar.
Y otra precaución. Tenga cuidado al usar el método ClearHeaders de la clase HttpResponse. Puede darle algunos moretones si lo usa imprudentemente. Al igual que me dio.
Después de redirigir en el evento ActionFilterAttribute, las consecuencias de borrar todos los encabezados están perdiendo todos los datos de la sesión y los datos en el almacenamiento TempData. Es más seguro redirigir desde una Acción o no borrar los encabezados cuando se lleva a cabo la redirección.
Pensándolo bien, desaliento a todos a usar el método ClearHeaders. Es mejor eliminar los encabezados por separado. Y para configurar correctamente el encabezado de Cache-Control, estoy usando este código:
filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
filterContext.HttpContext.Response.Cache.AppendCacheExtension("no-store, must-revalidate");
Vea este enlace a un estudio de caso sobre almacenamiento en caché:
http://securityevaluators.com/knowledge/case_studies/caching/
Resumen, según el artículo, solo Cache-Control: no-store
funciona en Chrome, Firefox e IE. IE acepta otros controles, pero Chrome y Firefox no. El enlace es una buena lectura completa con el historial de almacenamiento en caché y documentación de prueba de concepto.
Además de los encabezados, considera servir tu página a través de https . Muchos navegadores no almacenan en caché https por defecto.
Además, solo para una buena medida, asegúrese de restablecer el archivo ExpiresDefault
en su .htaccess
archivo si lo está utilizando para habilitar el almacenamiento en caché.
ExpiresDefault "access plus 0 seconds"
Después, puede utilizar ExpiresByType
para establecer valores específicos para los archivos que desea almacenar en caché:
ExpiresByType image/x-icon "access plus 3 month"
Esto también puede ser útil si el navegador almacena sus archivos dinámicos, por ejemplo, php, etc., y no puede entender por qué. Compruebe ExpiresDefault
.
No tuve suerte con los <head><meta>
elementos. Agregar parámetros relacionados con la memoria caché HTTP directamente (fuera del documento HTML) realmente funciona para mí.
A continuación se muestra un código de muestra en Python que utiliza web.header
llamadas web.py. Redacté a propósito mi código de utilidad irrelevante personal.
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()
Para completar BalusC -> answer Si está utilizando perl, puede usar CGI para agregar encabezados HTTP.
Utilizando 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
))
);
}
Utilizando 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>
Nota: cuando intenté usar el META html, los navegadores los ignoraron y guardaron la página en caché.
//In .net MVC
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public ActionResult FareListInfo(long id)
{
}
// In .net webform
<%@ OutputCache NoStore="true" Duration="0" VaryByParam="*" %>