Como controlar o cache de páginas da web em todos os navegadores?

Nossas investigações nos mostraram que nem todos os navegadores respeitam as diretivas de cache http de maneira uniforme.

Por razões de segurança, não queremos que determinadas páginas do nosso aplicativo sejam armazenadas em cache pelo navegador da web. Isso deve funcionar pelo menos para os seguintes navegadores:

  • Internet Explorer 6 ou superior
  • Firefox 1.5+
  • Safari 3+
  • Ópera 9+
  • cromada

Nossa exigência veio de um teste de segurança. Depois de sair do nosso site, você pode pressionar o botão Voltar e ver as páginas em cache.

Introdução

O conjunto mínimo correto de headers que funciona em todos os clientes (e proxies) mencionados:

Cache-Control: no-cache, no-store, must-revalidate Pragma: no-cache Expires: 0 

O Cache-Control é de acordo com a especificação HTTP 1.1 para clientes e proxies (e implicitamente exigido por alguns clientes próximos a Expires ). O Pragma é de acordo com as especificações HTTP 1.0 para clientes pré-históricos. O Expires é de acordo com as especificações HTTP 1.0 e 1.1 para clientes e proxies. No HTTP 1.1, o Cache-Control tem precedência sobre Expires , portanto, é apenas para proxies HTTP 1.0.

Se você não se importa com o IE6 e seu cache quebrado ao servir páginas em HTTPS com apenas no-store , você pode omitir Cache-Control: no-cache .

 Cache-Control: no-store, must-revalidate Pragma: no-cache Expires: 0 

Se você não se importa com o IE6 nem com clientes HTTP 1.0 (o HTTP 1.1 foi introduzido em 1997), então você pode omitir o Pragma .

 Cache-Control: no-store, must-revalidate Expires: 0 

Se você não se importa com proxies HTTP 1.0, então você pode omitir Expires .

 Cache-Control: no-store, must-revalidate 

Por outro lado, se o servidor include automaticamente um header de Date válido, você poderá, teoricamente, omitir também o Cache-Control e confiar apenas em Expires .

 Date: Wed, 24 Aug 2016 18:32:02 GMT Expires: 0 

Mas isso pode falhar se, por exemplo, o usuário final manipular a data do sistema operacional e o software cliente estiver contando com ela.

Outros parâmetros de Cache-Control , como max-age são irrelevantes se os parâmetros de Cache-Control mencionados acima forem especificados. O header Last-Modified conforme incluído na maioria das outras respostas aqui, é interessante apenas se você quiser armazenar o pedido em cache, para que você não precise especificá-lo.

Como definir isso?

Usando PHP:

 header("Cache-Control: no-cache, no-store, must-revalidate"); // HTTP 1.1. header("Pragma: no-cache"); // HTTP 1.0. header("Expires: 0"); // Proxies. 

Usando o Java Servlet ou 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. 

Usando o 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 a API da Web do 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()); 

Usando o 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. 

Usando 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, ou 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') ) ) 

Usando o 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 o arquivo .htaccess Apache:

  Header set Cache-Control "no-cache, no-store, must-revalidate" Header set Pragma "no-cache" Header set Expires 0  

Usando HTML4:

    

Meta tags HTML versus headers de resposta HTTP

É importante saber que, quando uma página HTML é veiculada em uma conexão HTTP e um header está presente nos headers de resposta HTTP e nas tags HTML , a especificada no header de resposta HTTP terá precedência sobre a meta tag HTML. A meta tag HTML só será usada quando a página for visualizada no sistema de arquivos do disco local por meio de um file:// URL. Veja também o capítulo sobre especificações W3 em HTML 5.2.2 . Tome cuidado com isso quando você não especificá-los programaticamente, porque o servidor pode include alguns valores padrão.

Geralmente, é melhor você não especificar as metatags HTML para evitar confusões e começar a usar headers de resposta HTTP. Além disso, especificamente, as tags são inválidas no HTML5. Apenas os valores http-equiv listados na especificação HTML5 são permitidos.

Verificando os Cabeçalhos de Resposta HTTP Reais

Para verificar um e outro, você pode ver / depurá-los no monitor de tráfego HTTP do conjunto de ferramentas de desenvolvedor do webbrowser. Você pode acessá-lo pressionando F12 no Chrome / Firefox23 + / IE9 + e, em seguida, abrindo o painel da guia “Rede” ou “Rede” e clicando na solicitação HTTP de interesse para descobrir todos os detalhes sobre a solicitação e a resposta HTTP. A captura de canvas abaixo é do Chrome:

Conjunto de ferramentas do desenvolvedor do Chrome Monitor de tráfego HTTP mostrando cabeçalhos de resposta HTTP em stackoverflow.com

Eu quero definir esses headers em downloads de arquivos também

Primeiro de tudo, esta pergunta e resposta é direcionada em “páginas da web” (páginas HTML), não “downloads de arquivos” (PDF, zip, Excel, etc). É melhor que você os coloque em cache e faça uso de algum identificador de versão de arquivo em algum lugar no caminho do URI ou no querystring para forçar um redownload em um arquivo alterado. Ao aplicar esses headers sem cache nos downloads de arquivos, tenha cuidado com o bug do IE7 / 8 ao exibir um download de arquivo via HTTPS em vez de HTTP. Para detalhes, veja IE não pode baixar foo.jsf. IE não foi capaz de abrir este site. O site solicitado está indisponível ou não pode ser encontrado .

(ei, todo mundo: por favor não copie e cole todos os headers que você pode encontrar)

Primeiro de tudo, o histórico do botão Voltar não é um cache :

O modelo de atualização (Seção 4.2) não se aplica necessariamente aos mecanismos do histórico. Ou seja, um mecanismo de histórico pode exibir uma representação anterior, mesmo que tenha expirado.

Na antiga especificação HTTP, o texto era ainda mais forte, explicitamente dizendo aos navegadores para desconsiderarem as diretivas de cache para o histórico do botão de retorno.

Voltar deve voltar no tempo (até o momento em que o usuário estava logado). Não navega para frente para um URL aberto anteriormente.

No entanto, na prática, o cache pode influenciar o botão Voltar, em circunstâncias muito específicas:

  • A página deve ser entregue via HTTPS , caso contrário, esse impedimento de cache não será confiável. Além disso, se você não estiver usando HTTPS, sua página ficará vulnerável a fazer o login de muitas outras maneiras.
  • Você deve enviar Cache-Control: no-store, must-revalidate (alguns navegadores observam no-store e alguns observam must-revalidate )

Você nunca precisa de:

  • com headers de cache – não funciona de todo. Totalmente inútil.
  • post-check / pre-check – é uma diretiva somente para o IE que se aplica apenas a resources em cache .
  • Enviando o mesmo header duas vezes ou em doze partes. Alguns fragments do PHP lá fora, na verdade, substituem os headers anteriores, resultando em apenas o último sendo enviado.

Se você quiser, você pode adicionar:

  • no-cache ou max-age=0 , o que tornará o recurso (URL) “obsoleto” e exigirá que os navegadores verifiquem com o servidor se houver uma versão mais recente ( no-store já implica isso ainda mais forte).
  • Expires com uma data no passado para clientes HTTP / 1.0 (embora os clientes reais somente HTTP / 1.0 sejam completamente inexistentes atualmente).

Bônus: O novo RFC de armazenamento em cache HTTP .

Conforme declarado porneL, o que você deseja não é desativar o cache, mas desativar o buffer de histórico. Navegadores diferentes têm suas próprias maneiras sutis de desabilitar o buffer de histórico.

No Chrome (v28.0.1500.95 m), podemos fazer isso apenas pelo Cache-Control: no-store .

No FireFox (v23.0.1), qualquer um deles funcionará:

  1. Cache-Control: no-store

  2. Cache-Control: no-cache (somente https)

  3. Pragma: no-cache (somente https)

  4. Vary: * (apenas https)

No Opera (v12.15), só podemos fazer isso pelo Cache-Control: must-revalidate (somente https).

No Safari (v5.1.7, 7534.57.2) qualquer um desses funcionará:

  1. Cache-Control: no-store
    em html

  2. Cache-Control: no-store (somente https)

No IE8 (v8.0.6001.18702IC) qualquer um deles funcionará:

  1. Cache-Control: must-revalidate, max-age=0

  2. Cache-Control: no-cache

  3. Cache-Control: no-store

  4. Cache-Control: must-revalidate
    Expires: 0

  5. Cache-Control: must-revalidate
    Expires: Sat, 12 Oct 1991 05:00:00 GMT

  6. Pragma: no-cache (somente https)

  7. Vary: * (apenas https)

Combinar os itens acima nos dá essa solução que funciona para o Chrome 28, FireFox 23, IE8, Safari 5.1.7 e Opera 12.15: Cache-Control: no-store, must-revalidate (somente https)

Observe que o https é necessário porque o Opera não desativa o buffer de histórico para páginas http simples. Se você realmente não consegue obter https e está preparado para ignorar o Opera, o melhor que você pode fazer é:

 Cache-Control: no-store  

Abaixo, mostramos os logs brutos dos meus testes:

HTTP:

  1. Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *

    Falha: Opera 12.15
    Sucesso: Chrome 28, FireFox 23, IE8, Safari 5.1.7

  2. 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: *

    Falha: Opera 12.15
    Sucesso: Chrome 28, FireFox 23, IE8, Safari 5.1.7

  3. Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    Falha: Safari 5.1.7, Opera 12.15
    Sucesso: Chrome 28, FireFox 23, IE8

  4. 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: *
    Falha: Safari 5.1.7, Opera 12.15
    Sucesso: Chrome 28, FireFox 23, IE8

  5. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *

    Falha: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Sucesso: IE8

  6. 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: *

    Falha: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Sucesso: IE8

  7. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *

    Falha: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Sucesso: IE8

  8. 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: *

    Falha: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Sucesso: IE8

  9. Cache-Control: no-store
    Falha: Safari 5.1.7, Opera 12.15
    Sucesso: Chrome 28, FireFox 23, IE8

  10. Cache-Control: no-store

    Falha: Opera 12.15
    Sucesso: Chrome 28, FireFox 23, IE8, Safari 5.1.7

  11. Cache-Control: no-cache
    Falha: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Sucesso: IE8

  12. Vary: *
    Falha: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    Sucesso: nenhum

  13. Pragma: no-cache
    Falha: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    Sucesso: nenhum

  14. 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: *

    Falha: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Sucesso: IE8

  15. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *

    Falha: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Sucesso: IE8

  16. Cache-Control: must-revalidate, max-age=0
    Falha: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Sucesso: IE8

  17. Cache-Control: must-revalidate
    Expires: 0
    Falha: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Sucesso: IE8

  18. Cache-Control: must-revalidate
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Falha: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Sucesso: IE8

  19. Cache-Control: private, must-revalidate, proxy-revalidate, s-maxage=0
    Pragma: no-cache
    Vary: *

    Falha: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    Sucesso: nenhum

HTTPS:

  1. Cache-Control: private, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0

    Falha: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    Sucesso: nenhum

  2. Cache-Control: private, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT

    Falha: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    Sucesso: nenhum

  3. Vary: *
    Falha: Chrome 28, Safari 5.1.7, Opera 12.15
    Sucesso: FireFox 23, IE8

  4. Pragma: no-cache
    Falha: Chrome 28, Safari 5.1.7, Opera 12.15
    Sucesso: FireFox 23, IE8

  5. Cache-Control: no-cache
    Falha: Chrome 28, Safari 5.1.7, Opera 12.15
    Sucesso: FireFox 23, IE8

  6. Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
    Falha: Chrome 28, Safari 5.1.7, Opera 12.15
    Sucesso: FireFox 23, IE8

  7. Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    Falha: Chrome 28, Safari 5.1.7, Opera 12.15
    Sucesso: FireFox 23, IE8

  8. 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: *
    Falha: Chrome 28, Safari 5.1.7, Opera 12.15
    Sucesso: FireFox 23, IE8

  9. Cache-Control: must-revalidate
    Falha: Chrome 28, FireFox 23, IE8, Safari 5.1.7
    Sucesso: Opera 12.15

  10. Cache-Control: private, must-revalidate, proxy-revalidate, s-maxage=0

    Falha: Chrome 28, FireFox 23, IE8, Safari 5.1.7
    Sucesso: Opera 12.15

  11. Cache-Control: must-revalidate, max-age=0
    Falha: Chrome 28, FireFox 23, Safari 5.1.7
    Sucesso: IE8, Opera 12.15

  12. 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: *

    Falha: Chrome 28, Safari 5.1.7
    Sucesso: FireFox 23, IE8, Opera 12.15

  13. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *

    Falha: Chrome 28, Safari 5.1.7
    Sucesso: FireFox 23, IE8, Opera 12.15

  14. Cache-Control: no-store
    Falha: Opera 12.15
    Sucesso: Chrome 28, FireFox 23, IE8, Safari 5.1.7

  15. Cache-Control: private, no-cache, no-store, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *

    Falha: Opera 12.15
    Sucesso: Chrome 28, FireFox 23, IE8, Safari 5.1.7

  16. 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: *

    Falha: Opera 12.15
    Sucesso: Chrome 28, FireFox 23, IE8, Safari 5.1.7

  17. Cache-Control: private, no-cache
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    Falha: Chrome 28, Safari 5.1.7, Opera 12.15
    Sucesso: FireFox 23, IE8

  18. Cache-Control: must-revalidate
    Expires: 0
    Falha: Chrome 28, FireFox 23, Safari 5.1.7,
    Sucesso: IE8, Opera 12.15

  19. Cache-Control: must-revalidate
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Falha: Chrome 28, FireFox 23, Safari 5.1.7,
    Sucesso: IE8, Opera 12.15

  20. Cache-Control: private, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0

    Falha: Chrome 28, FireFox 23, Safari 5.1.7,
    Sucesso: IE8, Opera 12.15

  21. Cache-Control: private, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT

    Falha: Chrome 28, FireFox 23, Safari 5.1.7,
    Sucesso: IE8, Opera 12.15

  22. Cache-Control: private, must-revalidate
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    Falha: Chrome 28, Safari 5.1.7
    Sucesso: FireFox 23, IE8, Opera 12.15

  23. Cache-Control: no-store, must-revalidate
    Falha: nenhum
    Sucesso: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15

Eu achei a rota web.config útil (tentei adicioná-la à resposta, mas parece que não foi aceita, então postar aqui)

              

E aqui está a maneira express / node.js de fazer o mesmo:

 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(); }); 

Eu achei que todas as respostas nesta página ainda tinham problemas. Em particular, notei que nenhum deles impediria o IE8 de usar uma versão em cache da página quando você a acessasse pressionando o botão Voltar.

Depois de muita pesquisa e testes, descobri que os únicos dois headers que eu realmente precisava eram:

Cache-Control: no-store
Variar: *

Para uma explicação do header Vary, confira http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.6

No IE6-8, FF1.5-3.5, Chrome 2-3, Safari 4 e Opera 9-10, esses headers fizeram com que a página fosse solicitada ao servidor quando você clica em um link para a página ou coloca o URL diretamente na barra de endereço. Isso cobre cerca de 99% de todos os navegadores em uso a partir de janeiro de 2010.

No IE6 e no Opera 9-10, pressionar o botão Voltar ainda fazia com que a versão em cache fosse carregada. Em todos os outros navegadores que testei, eles buscaram uma nova versão do servidor. Até agora, não encontrei nenhum conjunto de headers que faça com que esses navegadores não retornem versões em cache de páginas quando você apertar o botão Voltar.

Atualização: Depois de escrever esta resposta, percebi que o nosso servidor web está se identificando como um servidor HTTP 1.0. Os headers que listei são os corretos para que as respostas de um servidor HTTP 1.0 não sejam armazenadas em cache pelos navegadores. Para um servidor HTTP 1.1, veja a resposta do BalusC.

Depois de um pouco de pesquisa, surgiu a seguinte lista de headers que pareciam abranger a maioria dos navegadores:

  • Expira em : Mon, 26 jul 1997 05:00:00 GMT
  • Cache-Control : no-cache , privado, deve-revalidar , max-stale = 0, pós-verificação = 0, pré-verificação = 0 no-store
  • Pragma : sem cache

No ASP.NET nós adicionamos estes usando o seguinte trecho:

 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 em: http://forums.asp.net/t/1013531.aspx

O uso do header pragma na resposta é um conto de esposas. RFC2616 apenas define como um header de solicitação

http://www.mnot.net/cache_docs/#PRAGMA

ISENÇÃO DE RESPONSABILIDADE: Eu sugiro fortemente ler a resposta do @BalusC. Depois de ler o seguinte tutorial de cache: http://www.mnot.net/cache_docs/ (eu recomendo que você leia também), eu acredito que seja correto. No entanto, por razões históricas (e porque eu mesmo testei), includeei minha resposta original abaixo:


Eu tentei a resposta ‘aceita’ para PHP, o que não funcionou para mim. Então eu fiz uma pequena pesquisa, encontrei uma pequena variante, testei e funcionou. Aqui 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 MYH:i:s') . ' GMT'); header ('Pragma: no-cache'); 

Isso deve funcionar. O problema é que ao definir a mesma parte do header duas vezes, se o false não for enviado como o segundo argumento para a function de header, a function de header simplesmente sobrescreverá a chamada anterior do header() . Então, ao definir o Cache-Control , por exemplo, se alguém não quiser colocar todos os argumentos em uma chamada de function header() , ele deve fazer algo assim:

 header('Cache-Control: this'); header('Cache-Control: and, this', false); 

Veja mais documentação completa aqui .

Há um bug no IE6

O conteúdo com “Content-Encoding: gzip” é sempre armazenado em cache, mesmo se você usar “Cache-Control: no-cache”.

http://support.microsoft.com/kb/321722

Você pode desativar a compactação gzip para usuários do IE6 (verifique o agente do usuário para “MSIE 6”)

O RFC para HTTP 1.1 diz que o método apropriado é adicionar um header HTTP para:

Cache-Control: no-cache

Os navegadores mais antigos podem ignorar isso se não forem compatíveis com o HTTP 1.1. Para aqueles que você pode experimentar o header:

Pragma: sem cache

Isso também deve funcionar para navegadores HTTP 1.1.

Essas diretivas não reduzem nenhum risco de segurança. Eles realmente pretendem forçar os UAs a atualizar informações voláteis, não impedindo que os UAs retenham informações. Veja essa pergunta semelhante . No mínimo, não há garantia de que quaisquer roteadores, proxies, etc. também não ignorem as diretivas de armazenamento em cache.

Em uma nota mais positiva, as políticas relacionadas ao access físico aos computadores, instalação de software e afins o colocarão à frente da maioria das empresas em termos de segurança. Se os consumidores dessas informações forem membros do público, a única coisa que você realmente pode fazer é ajudá-los a entender que, uma vez que a informação chega à sua máquina, essa máquina é de sua responsabilidade, não da sua.

A documentação do PHP para a function de header possui um exemplo bastante completo (contribuído por terceiros):

  header('Pragma: public'); header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past header('Last-Modified: '.gmdate('D, d MYH: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); 

Se você estiver enfrentando problemas de download com o IE6-IE8 sobre SSL e cache: header sem cache (e valores semelhantes) com arquivos do MS Office, é possível usar cache: private, no-store header e return file na solicitação POST. Funciona.

no meu caso eu corrigir o problema no chrome com este

 

onde preciso limpar o conteúdo de um dado de formulário anterior quando os usuários clicam no botão de volta por motivos de segurança

Para o ASP.NET Core, crie uma class simples de middleware:

 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 ); } } 

então registre-o no Startup.cs

 app.UseMiddleware(); 

Certifique-se de adicionar isso em algum lugar depois

 app.UseStaticFiles(); 

A configuração do header http modificado para uma data em 1995 geralmente funciona.

Aqui está um exemplo:

 Data de expiração: 15 de novembro de 1995 04:58:08 GMT
 Última modificação: Wed, 15 de novembro de 1995 04:58:08 GMT
 Cache-Control: no-cache, deve-revalidar

Eu tive resultados melhores e mais consistentes em todos os navegadores, configurando o Pragma: no-cache

Os headers na resposta fornecida pelo BalusC não impedem que o Safari 5 (e possivelmente as versões mais antigas também) exibam o conteúdo do cache do navegador ao usar o botão Voltar do navegador. Uma maneira de evitar isso é adicionar um atributo manipulador de events onunload vazio à tag body:

  

Este hack aparentemente quebra o cache de back-forward no Safari: Existe um evento onload entre navegadores ao clicar no botão Voltar?

A resposta aceita não parece funcionar para o IIS7 +, passando pelo grande número de perguntas sobre os headers de cache não serem enviados no II7:

  • Algo está forçando respostas a ter controle de cache: privado no IIS7
  • IIS7: configuração de cache não está funcionando … por que?
  • Cabeçalhos de Cache do Cliente ASP.NET MVC do IIS7 + Não Funcionando
  • Definir o controle de cache para páginas aspx
  • Cache-control: no-store, deve-revalidar não enviado ao navegador do cliente no IIS7 + ASP.NET MVC

E assim por diante

A resposta aceita é correta, na qual os headers devem ser definidos, mas não como devem ser definidos. Desta forma, funciona com o IIS7:

 Response.Cache.SetCacheability(HttpCacheability.NoCache); Response.Cache.AppendCacheExtension("no-store, must-revalidate"); Response.AppendHeader("Pragma", "no-cache"); Response.AppendHeader("Expires", "-1"); 

A primeira linha define Cache-control para no-cache , e a segunda linha adiciona os outros atributos no-store, must-revalidate

Além dos headers, considere servir sua página via https . Muitos navegadores não armazenam em cache https por padrão.

 //In .net MVC [OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")] public ActionResult FareListInfo(long id) { } // In .net webform <%@ OutputCache NoStore="true" Duration="0" VaryByParam="*" %> 

Para completar o BalusC -> ANSWER Se você estiver usando o perl, você pode usar o CGI para adicionar headers HTTP.

Usando o 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

  FileETag None  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"  

Note: When I tried to use the html META, browsers ignored them and cached the page.

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 eg php, etc. are being cached by the browser, and you can’t figure out why. Check ExpiresDefault .

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"); 

I had no luck with 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
         experimentar:
            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()

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.