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


1552

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 em nosso aplicativo sejam armazenadas em cache, sempre, pelo navegador da web. Isso deve funcionar para pelo menos os seguintes navegadores:

  • Internet Explorer 6 ou superior
  • Firefox 1.5 ou superior
  • Safari 3+
  • Opera 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 visualizar as páginas em cache.


Apenas para o ipad Safari, [this] [1] ajuda? [1]: stackoverflow.com/questions/24524248/…
Bakhshi

O mais simples é usar: max-age = 10. Isso não é perfeito porque a página será armazenada em cache por 10 segundos. Mas é a menor solução "espaguete de cabeçalho" por aí. Além disso, isso às vezes fornece um grande aumento de desempenho em sites dinâmicos que usam proxies reversos. (Seu script php lenta será chamada uma vez a cada 10 segundos e, então, ser armazenados em cache pelo proxy reverso uma vez por 10 segundos é muito melhor do que uma vez por visitante.)
Olá Mundo


3
Obrigado por essa ótima pergunta. Por curiosidade, qual pode ser a situação que faz com que você envie alguns dados enquanto não deseja que o destinatário os salve por "razões de segurança" . você já os enviou!
precisa saber é o seguinte

1
@ Contador: em seu cenário, o usuário havia desconectado. Quem pode garantir que o próximo usuário humano nesse User Agent será a pessoa que acabou de sair?
Fabien Haddadi

Respostas:


2579

Introdução

O conjunto mínimo correto de cabeçalhos 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é pelo HTTP 1.1 especificação para clientes e proxies (e implicitamente exigido por alguns clientes ao lado Expires). O valor Pragmaé de acordo com a especificação 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, a Cache-Controlprecedência tem precedência Expires; portanto, é apenas para proxies HTTP 1.0.

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

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

Se você não se importa com os clientes IE6 e HTTP 1.0 (HTTP 1.1 foi introduzido em 1997), poderá omitir Pragma.

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

Se você também não se importa com proxies HTTP 1.0, poderá omitir Expires.

Cache-Control: no-store, must-revalidate

Por outro lado, se o servidor incluir automaticamente um Datecabeçalho válido , você também poderá omitir teoricamente Cache-Controle confiar Expiresapenas nele .

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 confiar nela.

Outros Cache-Controlparâmetros, como max-agesão irrelevantes, se os Cache-Controlparâmetros acima mencionados forem especificados. O Last-Modifiedcabeçalho, incluído na maioria das outras respostas aqui, é interessante apenas se você realmente deseja armazenar em cache a solicitação, portanto, não é necessário especificá-la.

Como configurá-lo?

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 Java Servlet, ou 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 o ASP.NET Core v3

// using Microsoft.Net.Http.Headers
Response.Headers[HeaderNames.CacheControl] = "no-cache, no-store, must-revalidate";
Response.Headers[HeaderNames.Expires] = "0";
Response.Headers[HeaderNames.Pragma] = "no-cache";

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:

headers["Cache-Control"] = "no-cache, no-store, must-revalidate" # HTTP 1.1.
headers["Pragma"] = "no-cache" # HTTP 1.0.
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 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 .htaccessarquivo 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>

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

Meta tags HTML x cabeçalhos de resposta HTTP

Importante saber é que quando uma página HTML é servido em uma conexão HTTP, e um cabeçalho está presente em ambos os cabeçalhos de resposta HTTP e HTML <meta http-equiv>marcas, então o especificado no cabeçalho de resposta HTTP terá precedência sobre a meta tag HTML. A metatag HTML só será usada quando a página for visualizada em um sistema de arquivos em disco local por meio de um file://URL. Veja também o capítulo 5.2.2 das especificações HTML do W3 . Tome cuidado com isso quando você não os especificar programaticamente, porque o servidor da Web pode incluir alguns valores padrão.

Geralmente, é melhor você não especificar as meta tags HTML para evitar confusão por iniciantes e confiar em cabeçalhos de resposta HTTP rígidos. Além disso, especificamente essas <meta http-equiv>tags são inválidas no HTML5. Somente os http-equivvalores listados na especificação HTML5 são permitidos.

Verificando os cabeçalhos de resposta HTTP reais

Para verificar um e outro, você pode vê-los / depurá-los no monitor de tráfego HTTP do conjunto de ferramentas do desenvolvedor do navegador da web. Você pode chegar lá pressionando F12 no Chrome / Firefox23 + / IE9 + e 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 resposta HTTP. A captura de tela abaixo é do Chrome:

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

Também quero definir esses cabeçalhos nos downloads de arquivos

Antes de tudo, esta pergunta e resposta são direcionadas para "páginas da web" (páginas HTML), não para "downloads de arquivos" (PDF, zip, Excel, etc). É melhor colocá-los em cache e usar algum identificador de versão de arquivo em algum lugar no caminho do URI ou na string de consulta para forçar um download novamente em um arquivo alterado. De qualquer maneira, ao aplicar esses cabeçalhos sem cache nos downloads de arquivos, tome cuidado com o bug do IE7 / 8 ao enviar um download de arquivo por HTTPS em vez de HTTP. Para detalhes, consulte IE não pode baixar foo.jsf. O IE não conseguiu abrir este site. O site solicitado não está disponível ou não pode ser encontrado .


16
Isso não parece estar completo. Eu tentei esta solução no IE 8 e descobri que o navegador carregará uma versão em cache quando você clicar no botão Voltar.
Mike Ottum

16
Provavelmente sua metodologia de teste estava errada. Talvez a página já estivesse no cache? Talvez os cabeçalhos estivessem incorretos / anulados? Talvez você estivesse olhando para a solicitação errada? Etc ..
BalusC

8
Na verdade, confirmo que essa abordagem é incompleta e causa problemas no IE8, ou pelo menos em algumas circunstâncias. Especificamente, ao usar o IE8 para buscar um recurso por SSL, o IE8 se recusará a buscar o recurso pela segunda vez (ou mesmo após uma primeira tentativa, dependendo dos cabeçalhos usados). Veja o blog de EricLaw , por exemplo.
haylem

21
Gostaria de acrescentar que isso é essencialmente o que o Bank of America faz. Se você olhar para os cabeçalhos de resposta e traduzir isso para aspx, eles estão fazendo: Response.AppendHeader ("Cache-Control", "no-cache, no-store, must-revalidate"); Response.AppendHeader ("Expira", "Qui, 01 de dezembro de 1994 16:00:00 GMT"); Eu acho que, se é bom o suficiente para eles, é bom o suficiente para mim.
John John

8
@ John: Esse cabeçalho expira é exatamente o valor de exemplo na especificação HTTP 1.0 . Funciona, mas é um tanto ridículo usar exatamente esse carimbo de data e hora.
BalusC

244

(ei pessoal: não copie e cole sem pensar todos os cabeçalhos que 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 de 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, dizendo explicitamente aos navegadores que desconsiderassem as diretivas de cache para o histórico do botão voltar.

Voltar deve voltar no tempo (até o momento em que o usuário estava logado). Ele não navega 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 por HTTPS , caso contrário, esse bloqueio de cache não será confiável. Além disso, se você não estiver usando HTTPS, sua página estará vulnerável ao roubo de login de várias outras maneiras.
  • Você deve enviar Cache-Control: no-store, must-revalidate(alguns navegadores observam no-storee outros observam must-revalidate)

Você nunca precisa de:

  • <meta>com cabeçalhos de cache - não funciona. Totalmente inútil.
  • post-check/ pre-check- é diretiva apenas para o IE que se aplica apenas a recursos capturáveis .
  • Enviando o mesmo cabeçalho duas vezes ou em dezenas de partes. Alguns trechos de PHP por aí substituem os cabeçalhos anteriores, resultando no envio apenas do último.

Se você quiser, você pode adicionar:

  • no-cacheou max-age=0, o que tornará o recurso (URL) "obsoleto" e exigirá que os navegadores verifiquem com o servidor se há uma versão mais recente ( no-storejá implica isso ainda mais forte).
  • Expirescom uma data no passado para clientes HTTP / 1.0 (embora clientes reais apenas com HTTP / 1.0 não existam atualmente).

Bônus: o novo RFC de cache HTTP .


1
isso terá algum efeito colateral no desempenho do site em termos de tempo de carregamento? como nenhuma loja, sem cache, deve revalidar afetar o desempenho?
Raman Ghai

@RamanGhai A desativação do cache geralmente prejudica o desempenho (e as três opções mencionadas desativam o cache). Isso pode tornar os proxies de CDNs e ISP (por exemplo, comumente usados ​​por operadoras de telefonia móvel) ineficazes. Não prejudica a primeira carga por um novo usuário (exceto o problema do proxy), mas a navegação subsequente pode ser muito mais lenta.
Kornel

@porneL você declara que devemos enviar Cache-Control: must-revalidate. Por que não enviar Cache-Control: no-cacheuma vez que no-cachejá implicamust-revalidate ? w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.1
Pacerier

3
@Pacerier a relação de no-cachecom must-revalidateé verdadeira para o cache, mas o histórico anterior não é um cache. Caso especial de navegadores explícito must-revalidatepara controlar o comportamento do histórico .
Kornel

@porneL, Hmm, existe uma RFC de suporte que declara que é o comportamento desejado?
Pacerier 29/08/13

103

Como o @Kornel afirmou, o que você deseja não é desativar o cache, mas desativar o buffer do histórico. Navegadores diferentes têm suas próprias maneiras sutis de desativar o buffer do histórico.

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

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

  1. Cache-Control: no-store

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

  3. Pragma: no-cache (apenas https)

  4. Vary: * (apenas https)

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

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

  1. Cache-Control: no-store
    <body onunload=""> em html

  2. Cache-Control: no-store (apenas 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 (apenas https)

  7. Vary: * (apenas https)

A combinação dos itens acima fornece a solução que funciona no Chrome 28, FireFox 23, IE8, Safari 5.1.7 e Opera 12.15: Cache-Control: no-store, must-revalidate (somente https)

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

Cache-Control: no-store
<body onunload="">

Abaixo mostra 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: *
    <body onunload="">
    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: *
    <body onunload="">
    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: *
    <body onunload="">
    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: *
    <body onunload="">
    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: *
    <body onunload="">
    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: *
    <body onunload="">
    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
    <body onunload="">
    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: *
    <body onunload="">
    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: *
    <body onunload="">
    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: *
    <body onunload="">
    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
    <body onunload="">
    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
    <body onunload="">
    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
    <body onunload="">
    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: *
    <body onunload="">
    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: *
    <body onunload="">
    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: *
    <body onunload="">
    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: *
    <body onunload="">
    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
    <body onunload="">
    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
    <body onunload="">
    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: nenhuma
    Sucesso: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15


3
Eu sei que isso foi publicado há alguns anos, mas foi uma leitura interessante. Esse problema já me deixa louco há alguns meses, o corpo parece realmente saber como lidar com o controle de cache. Eu já vi algumas pessoas usando o, <body onunload="">mas parece mais uma maneira de contornar o problema real. Eu tentei usar o .htaccess e modificar os cabeçalhos dessa maneira, se eu usar HTTPS, deve funcionar dessa maneira? É principalmente o safari onde o problema surge mais.
21415 Jordan

4
@ Jordânia, de acordo com os logs acima, se você tiver HTTPS, a adição de um ditado Cache-Control: no-storefaria o truque. <body onunload="">só é necessário quando você não possui HTTPS.
Pacerier 26/11/15

37

Achei a rota web.config útil (tentei adicioná-la à resposta, mas não parece ter sido aceita, então poste aqui)

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

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

Para o web.config, eu modificaria um pouco para aplicar os cabeçalhos personalizados apenas aos scripts que sabemos serem carregados dinamicamente / usando requirejs. Supondo que seus scripts são encontrados em pasta do cliente: <caminho do local = "cliente"> ..... </ location>
Ibrahim ben Salah

Para quem está se perguntando o que web.confé: É o principal arquivo de configuração e configuração de um ASP.NETaplicativo da web. É um documento XML que reside no diretório raiz. ( wiki ).
outro

27

Eu descobri 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.

Após muita pesquisa e teste, descobri que os únicos dois cabeçalhos de que realmente precisava eram:

Controle de cache: no-store
Vary: *

Para obter uma explicação do cabeçalho 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 cabeçalhos faziam 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 desde 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 versão nova do servidor. Até agora, não encontrei nenhum conjunto de cabeçalhos que fizesse com que esses navegadores não retornassem versões em cache das páginas quando você pressionava o botão Voltar.

Atualização: Depois de escrever esta resposta, percebi que nosso servidor da web estava se identificando como um servidor HTTP 1.0. Os cabeçalhos listados 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 .


4
Isso funciona para o botão voltar do IE8 !! Depois de tentar de tudo em todas as outras sugestões, adicionar o cabeçalho "Vary: *" é aparentemente a única coisa que pode forçar o IE8 a recarregar a página quando o usuário pressiona o botão Voltar. E isso faz o trabalho em HTTP / 1.1 servidores.
precisa

Combinado com os cabeçalhos sugeridos por BarlusC, além de um trecho JS que chama window.location.reload () quando o evento onPageShow é acionado com o atributo "persisted" (necessário para o Safari), todos os navegadores testados com êxito forçam uma recarga do servidor quando o usuário usa o botão Voltar.
precisa

1
@CoreDumpError, oh, você não deve assumir que o JavaScript está ativado.
Pacerier

@Pacerier Na época em que escrevi a resposta em 2010, isso funcionava no que eram as versões mais recentes do Safari e do Opera, com o nosso servidor se identificando como um servidor HTTP 1.0. Infelizmente, não tenho mais como testar isso com facilidade, por isso não posso dizer nada definitivo sobre as versões mais recentes desses navegadores.
Chris Vasselli

Quais foram as versões do navegador que você testou?
Pacerier

21

Após um pouco de pesquisa, criamos a seguinte lista de cabeçalhos que pareciam cobrir a maioria dos navegadores:

No ASP.NET, adicionamos esses itens usando o seguinte 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", "Mon, 26 Jul 1997 05:00:00 GMT"); // HTTP 1.0 

Encontrado em: http://forums.asp.net/t/1013531.aspx


36
@art: Ainda mais problemático é que o 26 de julho de 1997 foi um sábado, não uma segunda-feira ... #
1313 de C12

5
Cache-Control: no-cachee Cache-Control: privateconflito - você nunca deve reunir os dois: o primeiro diz aos navegadores e proxies para não armazenar em cache, o segundo diz aos proxies para não armazenar em cache, mas permite que os navegadores mantenham sua própria cópia privada. Não tenho certeza de qual configuração o navegador seguirá, mas é improvável que seja consistente entre navegadores e versões.
Keith

Não use pré-verificação e pós-verificação. blogs.msdn.com/b/ieinternals/archive/2009/07/20/…
EricLaw

isso não funcionou para mim - usando o asp.net 4.5, o código é executado, mas não produz o resultado necessário. Eu tive que seguir isso: stackoverflow.com/questions/22443932/…
Andy

8

O uso do cabeçalho pragma na resposta é um conto de mulheres. RFC2616 define apenas como um cabeçalho de solicitação

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


4
Este é um bom exemplo de por que você precisa ir além das especificações. Se as especificações fossem sempre claras, não haveria muito sentido em sites como o StackOverflow. Da Microsoft Para fins de compatibilidade com versões anteriores com servidores HTTP 1.0, o Internet Explorer suporta um uso especial do cabeçalho HTTP Pragma: no-cache. Se o cliente se comunicar com o servidor por uma conexão segura (https: //) e o servidor retornar um cabeçalho Pragma: sem cache com a resposta, o Internet Explorer não armazenará em cache a resposta.
michaelok

@michaelok: Sua referência é válida, mas perde o objetivo maior - defina um Controle de cache / expira adequado e você não precisa de pragma.
precisa saber é o seguinte

8

AVISO LEGAL: Sugiro fortemente que leia a resposta da @ BalusC. Depois de ler o seguinte tutorial sobre armazenamento em cache: http://www.mnot.net/cache_docs/ (eu recomendo que você leia também), acredito que esteja correto. No entanto, por razões históricas (e porque eu mesmo o testei), incluirei minha resposta original abaixo:


Eu tentei a resposta 'aceita' para PHP, que não funcionou para mim. Então 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 M Y H:i:s') . ' GMT');
header ('Pragma: no-cache');

Isso deve funcionar. O problema era que, ao definir a mesma parte do cabeçalho duas vezes, se falseo segundo argumento não for enviado para a função de cabeçalho, a função de cabeçalho simplesmente substituirá a header()chamada anterior . Portanto, ao definir Cache-Control, por exemplo, se alguém não deseja colocar todos os argumentos em uma header()chamada de função, deve fazer algo assim:

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

Veja a documentação mais completa aqui .


14
Isso é cheio de mitos. pré-verificação e pós-verificação são apenas para o IE, relevantes apenas para respostas em cache e o valor 0 é não operacional. max-stale é o cabeçalho de solicitação de proxy, não o cabeçalho de resposta do servidor. Expira aceita apenas um valor único. Mais de um fará com que esse cabeçalho seja ignorado.
Kornel

1
@porneL, você enviará uma resposta competitiva que lide com esses mitos corretamente?
Oddthinking 28/11/08

@Oddthinking, parece que stackoverflow.com/questions/49547/… é uma resposta competitiva.
Mike Ottum

@ Pacerier sim, como digo no aviso, use a resposta da BalusC.
Steven Oxley

8

Para o ASP.NET Core, crie uma classe 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 com Startup.cs

app.UseMiddleware<NoCacheMiddleware>();

Certifique-se de adicionar isso em algum lugar depois

app.UseStaticFiles();

Eu sugeriria usar constantes do Microsoft.Net.Http.Headers.HeaderNames em vez de literais de seqüência de caracteres "Cache-Controls", "Pragma" e "Expires".
Victor Sharovatov

7

Essas diretivas não atenuam nenhum risco à segurança. Eles realmente pretendem forçar os UA a atualizar informações voláteis, e não impedir que os UA retenham informações. Veja esta pergunta semelhante . No mínimo, não há garantia de que roteadores, proxies etc. também não ignorem as diretivas de cache.

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


7

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


6

O RFC para HTTP 1.1 diz que o método apropriado é adicionar um cabeçalho HTTP para:

Controle de cache: sem cache

Navegadores mais antigos podem ignorar isso se não forem adequadamente compatíveis com o HTTP 1.1. Para aqueles que você pode tentar o cabeçalho:

Pragma: sem cache

Isso também deve funcionar para navegadores HTTP 1.1.


1
A especificação indica que a resposta não deve ser reutilizada sem revalidação. É o Cache-Control: no-store que é o método oficial para indicar que a resposta nem sequer é armazenada em um cache em primeiro lugar.
AnthonyWJones

6

Definir o cabeçalho http modificado para alguma data em 1995 geralmente faz o truque.

Aqui está um exemplo:

Expira: quarta-feira, 15 de novembro de 1995, 04:58:08 GMT
Última modificação: quarta-feira, 15 de novembro de 1995 04:58:08 GMT
Controle de cache: sem cache, deve revalidar

1
Definir um Last-Modified há muito tempo não afeta o cache, exceto permitir que uma resposta em cache seja usada por mais tempo devido à revalidação heurística.
precisa saber é o seguinte

6

A documentação do PHP para a função de cabeçalho tem 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 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);

11
Isto está obviamente errado. As segundas chamadas ao cabeçalho () para Expira, Controle de cache e Pragma sobrescrevem completamente os valores definidos anteriormente.
Kornel

1
@porneL: Não, não substitua valores previamente definidos, pois ele passa false como um segundo parâmetro, dizendo para não substituir valores anteriores.
Julien Palard

1
@JulienPalard a resposta foi editada depois que eu fiz o meu comentário. Ainda não faz muito sentido.
Kornel

Não envie vários cabeçalhos de controle de cache se desejar trabalhar no IE antes da 9. NUNCA envie pré-verificação ou pós-verificação. blogs.msdn.com/b/ieinternals/archive/2009/07/20/…
EricLaw

6

Se você estiver enfrentando problemas de download com o IE6-IE8 sobre SSL e cache: cabeçalho sem cache (e valores semelhantes) com arquivos do MS Office, poderá usar o cache: cabeçalho privado, sem armazenamento e retornar o arquivo mediante solicitação POST. Funciona.


6

no meu caso, eu resolvo o problema no chrome com esse

<form id="form1" runat="server" autocomplete="off">

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


Meu problema do navegador mozilla 19.x também foi resolvido pelo snippet de código. autocomplete = "off". Obrigado.
23813 Satya

5

A resposta aceita não parece funcionar para o IIS7 +, respondendo ao grande número de perguntas sobre os cabeçalhos de cache que não foram enviados no II7:

E assim por diante

A resposta aceita está correta em que cabeçalhos devem ser definidos, mas não em como eles devem ser definidos. Dessa 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 é definida Cache-controlcomo no-cachee a segunda linha adiciona os outros atributosno-store, must-revalidate


Isso funciona para mim:Response.Cache.SetAllowResponseInBrowserHistory(false); Response.Cache.SetCacheability(HttpCacheability.NoCache); Response.Cache.SetNoStore(); Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);
Vilx-

4

Eu tive resultados melhores e mais consistentes em todos os navegadores, definindo Pragma: sem cache


4

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

<body onunload=""> 

Aparentemente, esse hack interrompe o cache de retorno no Safari: existe um evento de sobrecarga entre navegadores ao clicar no botão Voltar?


Legal, eu testei e isso realmente funciona no Safari (5.1.7), mas não no Opera.
Pacerier 29/08/13

4

Além disso, apenas para uma boa medida, redefina o arquivo ExpiresDefaultem seu .htaccessarquivo se você estiver usando isso para ativar o cache.

ExpiresDefault "access plus 0 seconds"

Depois, você pode usar ExpiresByTypepara definir valores específicos para os arquivos que deseja armazenar em cache:

ExpiresByType image/x-icon "access plus 3 month"

Isso também pode ser útil se seus arquivos dinâmicos, por exemplo, php, etc. estiverem sendo armazenados em cache pelo navegador, e você não conseguir entender o porquê. Verifique ExpiresDefault.


3

Além dos cabeçalhos, considere exibir sua página via https . Muitos navegadores não armazenam em cache https por padrão.


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

// In .net webform
<%@ OutputCache NoStore="true" Duration="0" VaryByParam="*" %>

2

Para concluir o BalusC -> RESPOSTA Se você estiver usando perl, poderá usar o CGI para adicionar cabeçalhos HTTP.

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

Usando o 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: Quando tentei usar o META html, os navegadores os ignoraram e armazenaram em cache a página.


0

Eu só quero salientar que, se alguém quiser impedir o armazenamento em cache de SOMENTE conteúdo dinâmico, a adição desses cabeçalhos adicionais deverá ser feita programaticamente.

Editei o arquivo de configuração do meu projeto para anexar cabeçalhos sem cache, mas isso também desabilitou o cache do conteúdo estático, o que geralmente não é desejável. A modificação dos cabeçalhos de resposta no código garante que as imagens e os arquivos de estilo sejam armazenados em cache.

Isso é bastante óbvio, mas ainda vale a pena mencionar.

E outra cautela. Cuidado ao usar o método ClearHeaders da classe HttpResponse. Pode causar algumas contusões se você a usar de forma imprudente. Como isso me deu.

Após o redirecionamento no evento ActionFilterAttribute, as consequências de limpar todos os cabeçalhos estão perdendo todos os dados da sessão e dados no armazenamento TempData. É mais seguro redirecionar de uma ação ou não limpar cabeçalhos quando o redirecionamento está ocorrendo.

Pensando bem, desencorajo todos a usar o método ClearHeaders. É melhor remover os cabeçalhos separadamente. E para definir o cabeçalho de controle de cache corretamente, eu estou usando este código:

filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
filterContext.HttpContext.Response.Cache.AppendCacheExtension("no-store, must-revalidate");

0

Não tive sorte com <head><meta>elementos. A adição direta de parâmetros relacionados ao cache HTTP (fora do documento HTML) realmente funciona para mim.

A seguir, exemplo de código em Python usando web.headerchamadas web.py. Eu propositadamente editei meu código de utilidade pessoal irrelevante.

    importar web
    sys de importação
    importar UTILIDADES PESSOAIS

    myname = "main.py"

    urls = (
        '/', 'main_class'
    )

    main = web.application (URLs, Globais ())

    render = web.template.render ("modelos /", base = "layout", cache = falso)

    classe main_class (objeto):
        def GET (auto):
            web.header ("Controle de cache", "sem cache, sem armazenamento, deve ser revalidado")
            web.header ("Pragma", "sem cache")
            web.header ("Expira", "0")
            retornar render.main_form ()

        def POST (auto):
            msg = "POSTADO:"
            form = web.input (função = Nenhuma)
            web.header ("Controle de cache", "sem cache, sem armazenamento, deve ser revalidado")
            web.header ("Pragma", "sem cache")
            web.header ("Expira", "0")
            retornar render.index_laid_out (saudação = msg + form.function)

    se __name__ == "__main__":
        nargs = len (sys.argv)
        # Verifique se há argumentos suficientes após o nome do programa python
        se nargs! = 2:
            LOG-AND-DIE ("% s: erro de linha de comando, nargs =% s, deve ser 2", meu nome, nargs)
        # Verifique se o número da porta TCP é numérico
        tentar:
            tcp_port = int (sys.argv [1])
        exceto exceção como e:
            LOG-AND-DIE ("% s: tcp_port = int (% s) falhou (não é um número inteiro)", meu nome, sys.argv [1])
        # Tudo está bem!
        JUST-LOG ("% s: executando na porta% d", meu nome, tcp_port)
        web.httpserver.runsimple (main.wsgifunc (), ("localhost", tcp_port))
        main.run ()


Isso já não está coberto muitas vezes nas respostas que estão no site há anos?
Martin Tournoij 10/08/16

As diretivas META funcionam no Internet Explorer e nas versões do Edge 18 e versões anteriores. Navegadores modernos não os suportam. Crbug.com/2763
EricLaw

0

Consulte este link para um estudo de caso sobre armazenamento em cache:

http://securityevaluators.com/knowledge/case_studies/caching/

Resumo, de acordo com o artigo, Cache-Control: no-storefunciona apenas no Chrome, Firefox e IE. O IE aceita outros controles, mas o Chrome e o Firefox não. O link é uma boa leitura, completa com o histórico de armazenamento em cache e documentação de prova de conceito.


0

Não tenho certeza se minha resposta parece simples e estúpida, e talvez ela já seja conhecida há muito tempo, mas como impedir que alguém use o botão voltar do navegador para visualizar suas páginas históricas seja um dos seus objetivos, você pode usar:

window.location.replace("https://www.example.com/page-not-to-be-viewed-in-browser-history-back-button.html");

Obviamente, isso pode não ser possível de ser implementado em todo o site, mas pelo menos para algumas páginas críticas, você pode fazer isso. Espero que isto ajude.


-1

você pode usar o bloco de localização para definir um arquivo individual em vez de todo o aplicativo obter o cache no IIS

 <location path="index.html">
    <system.webServer>
      <httpProtocol>
        <customHeaders>
          <add name="Cache-Control" value="no-cache" />
        </customHeaders>
      </httpProtocol>
    </system.webServer>
  </location>
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.