Come controllare la memorizzazione nella cache della pagina Web, su tutti i browser?

Le nostre indagini ci hanno mostrato che non tutti i browser rispettano le direttive della cache http in modo uniforms.

Per motivi di sicurezza, non vogliamo che alcune pagine della nostra applicazione vengano memorizzate nella cache, mai, dal browser web. Questo deve funzionare almeno per i seguenti browser:

  • Internet Explorer 6+
  • Firefox 1.5+
  • Safari 3+
  • Opera 9+
  • Cromo

Il nostro requisito proveniva da un test di sicurezza. Dopo aver effettuato il logout dal nostro sito Web, è ansible premere il pulsante Indietro e visualizzare le pagine memorizzate nella cache.

introduzione

Il set minimo corretto di intestazioni che funziona tra tutti i client citati (e i proxy):

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

Cache-Control è conforms alle specifiche HTTP 1.1 per client e proxy (e implicitamente richiesto da alcuni client accanto a Expires ). Il Pragma è per la specifica HTTP 1.0 per i client preistorici. The Expires è secondo le specifiche HTTP 1.0 e 1.1 per client e proxy. In HTTP 1.1, Cache-Control ha la precedenza su Expires , quindi dopo tutto è solo per i proxy HTTP 1.0.

Se non ti interessa IE6 e il suo caching rotto durante la pubblicazione di pagine su HTTPS con solo no-store , puoi omettere Cache-Control: no-cache .

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

Se non ti interessa IE6 né i client HTTP 1.0 (HTTP 1.1 è stato introdotto nel 1997), potresti omettere Pragma .

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

Se non ti interessa neanche i proxy HTTP 1.0, puoi omettere Expires .

 Cache-Control: no-store, must-revalidate 

D’altra parte, se il server include automaticamente un’intestazione Date valida, in teoria si può anche omettere Cache-Control e si può contare solo su Expires .

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

Ma ciò potrebbe fallire se ad esempio l’utente finale manipola la data del sistema operativo e il software client si basa su di esso.

Altri parametri di Cache-Control come max-age sono irrilevanti se vengono specificati i parametri di Cache-Control sopra menzionati. L’intestazione Last-Modified inclusa nella maggior parte delle altre risposte qui è interessante solo se si desidera effettivamente memorizzare nella cache la richiesta, quindi non è necessario specificarla.

Come impostarlo?

Utilizzando PHP:

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

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

Utilizzo di 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. 

Utilizzo dell’API Web 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()); 

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

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

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

Utilizzando Python / Pyramid:

 request.response.headerlist.extend( ( ('Cache-Control', 'no-cache, no-store, must-revalidate'), ('Pragma', 'no-cache'), ('Expires', '0') ) ) 

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

Utilizzando il file .htaccess Apache:

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

Utilizzando HTML4:

    

Meta tag HTML e intestazioni di risposta HTTP

È importante sapere che quando una pagina HTML viene servita su una connessione HTTP e un’intestazione è presente sia nelle intestazioni delle risposte HTTP che nei tag HTML , allora l’intestazione specificata nell’intestazione della risposta HTTP avrà la precedenza sopra il meta tag HTML. Il meta tag HTML verrà utilizzato solo quando la pagina viene visualizzata dal file system del disco locale tramite un file:// URL. Vedi anche W3 HTML spec capitolo 5.2.2 . Prenditi cura di questo quando non li specifichi a livello di codice, perché il server web può in particolare includere alcuni valori predefiniti.

In generale, è meglio non specificare i metatag HTML per evitare confusione tra gli avviatori e fare affidamento su intestazioni di risposta HTTP complesse. Inoltre, in particolare quei non sono validi in HTML5. Sono ammessi solo i valori http-equiv elencati nelle specifiche HTML5 .

Verifica delle intestazioni delle risposte HTTP effettive

Per verificare l’uno e l’altro, puoi vederli / debuggarli nel monitoraggio del traffico HTTP del set di strumenti per sviluppatori di webbrowser. Puoi arrivarci premendo F12 in Chrome / Firefox23 + / IE9 +, quindi aprendo il pannello “Rete” o “Rete”, quindi facendo clic sulla richiesta HTTP di interesse per scoprire tutti i dettagli sulla richiesta e risposta HTTP. Lo screenshot sottostante è di Chrome:

Set di strumenti per gli sviluppatori di Chrome Monitoraggio del traffico HTTP che mostra le intestazioni delle risposte HTTP su stackoverflow.com

Voglio impostare quelle intestazioni anche sui download di file

Prima di tutto, questa domanda e risposta è mirata su “pagine web” (pagine HTML), non su “download di file” (PDF, zip, Excel, ecc.). Faresti meglio a tenerli memorizzati nella cache e utilizzare qualche identificatore di versione del file da qualche parte nel percorso URI o querystring per forzare un nuovo download su un file modificato. Quando si applicano le intestazioni no-cache sui download di file in ogni caso, fare attenzione al bug di IE7 / 8 quando si serve un download di file su HTTPS anziché su HTTP. Per i dettagli, vedi IE non può scaricare foo.jsf. IE non è stato in grado di aprire questo sito internet. Il sito richiesto non è disponibile o non può essere trovato .

(ehi, tutti: per favore non copiare e incollare semplicemente tutte le intestazioni che riesci a trovare)

Prima di tutto, la cronologia del pulsante Indietro non è una cache :

Il modello di freschezza (Sezione 4.2) non si applica necessariamente ai meccanismi storici. Cioè, un meccanismo di cronologia può visualizzare una rappresentazione precedente anche se è scaduta.

Nella vecchia specifica HTTP la formulazione era ancora più forte, in quanto indicava esplicitamente ai browser di ignorare le direttive della cache per la cronologia dei pulsanti.

Back dovrebbe tornare indietro nel tempo (al momento in cui l’utente ha effettuato l’accesso). Non porta avanti a un URL aperto in precedenza.

Tuttavia, in pratica, la cache può influenzare il pulsante Indietro, in circostanze molto specifiche:

  • La pagina deve essere distribuita su HTTPS , altrimenti questo busting della cache non sarà affidabile. Inoltre, se non utilizzi HTTPS, la tua pagina è vulnerabile al furto di accesso in molti altri modi.
  • È necessario inviare Cache-Control: no-store, must-revalidate (alcuni browser osservano no-store e alcuni osservano must-revalidate )

Non hai mai bisogno di nessuno di:

  • con le intestazioni della cache – non funziona affatto. Totalmente inutile.
  • post-check / pre-check – è la direttiva solo IE che si applica solo alle risorse intercambiabili .
  • Invio della stessa intestazione due volte o in dozzina di parti. Alcuni frammenti di PHP là fuori in realtà sostituiscono le intestazioni precedenti, con la conseguenza che solo l’ultimo è stato inviato.

Se vuoi, puoi aggiungere:

  • no-cache o max-age=0 , che renderà la risorsa (URL) “obsoleta” e richiederà ai browser di verificare con il server se c’è una versione più recente (il no-store implica ancora di più).
  • Expires con una data nel passato per i client HTTP / 1.0 (anche se in questo momento i veri client HTTP / 1.0 sono completamente inesistenti).

Bonus: la nuova cache RFC HTTP .

Come indicato in precedenza, ciò che si desidera non è distriggersre la cache, ma distriggersre il buffer della cronologia. Browser diversi hanno i loro modi sottili per disabilitare il buffer della cronologia.

In Chrome (v28.0.1500.95 m) possiamo farlo solo con Cache-Control: no-store .

In FireFox (v23.0.1) ognuno di questi funzionerà:

  1. Cache-Control: no-store

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

  3. Pragma: no-cache (solo https)

  4. Vary: * (solo https)

In Opera (v12.15) possiamo farlo solo con Cache-Control: must-revalidate (solo https).

In Safari (v5.1.7, 7534.57.2) ognuno di questi funzionerà:

  1. Cache-Control: no-store
    in html

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

In IE8 (v8.0.6001.18702IC) ognuno di questi funzionerà:

  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 (solo https)

  7. Vary: * (solo https)

La combinazione di quanto sopra ci offre questa soluzione che funziona per Chrome 28, FireFox 23, IE8, Safari 5.1.7 e Opera 12.15: Cache-Control: no-store, must-revalidate (solo https)

Notare che https è necessario perché Opera non disabilita il buffer della cronologia per le semplici pagine http. Se davvero non riesci ad ottenere https e sei pronto a ignorare Opera, il meglio che puoi fare è questo:

 Cache-Control: no-store  

Di seguito sono riportati i log non elaborati dei miei test:

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

    Fail: Opera 12.15
    Successo: 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: *

    Fail: Opera 12.15
    Successo: 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: *
    Fail: Safari 5.1.7, Opera 12.15
    Successo: 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: *
    Fail: Safari 5.1.7, Opera 12.15
    Successo: 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: *

    Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Successo: 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: *

    Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Successo: IE8

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

    Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Successo: 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: *

    Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Successo: IE8

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

  10. Cache-Control: no-store

    Fail: Opera 12.15
    Successo: Chrome 28, FireFox 23, IE8, Safari 5.1.7

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

  12. Vary: *
    Fail: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    Successo: nessuno

  13. Pragma: no-cache
    Fail: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    Successo: nessuno

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

    Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Successo: IE8

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

    Fail: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    Successo: IE8

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

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

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

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

    Fail: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    Successo: nessuno

HTTPS:

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

    Fail: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    Successo: nessuno

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

    Fail: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    Successo: nessuno

  3. Vary: *
    Fail: Chrome 28, Safari 5.1.7, Opera 12.15
    Successo: FireFox 23, IE8

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

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

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

  7. Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    Fail: Chrome 28, Safari 5.1.7, Opera 12.15
    Successo: 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: *
    Fail: Chrome 28, Safari 5.1.7, Opera 12.15
    Successo: FireFox 23, IE8

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

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

    Fail: Chrome 28, FireFox 23, IE8, Safari 5.1.7
    Successo: Opera 12.15

  11. Cache-Control: must-revalidate, max-age=0
    Fail: Chrome 28, FireFox 23, Safari 5.1.7
    Successo: 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: *

    Fail: Chrome 28, Safari 5.1.7
    Successo: 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: *

    Fail: Chrome 28, Safari 5.1.7
    Successo: FireFox 23, IE8, Opera 12.15

  14. Cache-Control: no-store
    Fail: Opera 12.15
    Successo: 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: *

    Fail: Opera 12.15
    Successo: 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: *

    Fail: Opera 12.15
    Successo: 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: *
    Fail: Chrome 28, Safari 5.1.7, Opera 12.15
    Successo: FireFox 23, IE8

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

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

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

    Fail: Chrome 28, FireFox 23, Safari 5.1.7,
    Successo: 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

    Fail: Chrome 28, FireFox 23, Safari 5.1.7,
    Successo: IE8, Opera 12.15

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

  23. Cache-Control: no-store, must-revalidate
    Fail: nessuno
    Successo: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15

Ho trovato utile la rotta web.config (ho cercato di aggiungerla alla risposta ma non sembra essere stata accettata, quindi postare qui)

              

Ed ecco il modo express / node.js di fare lo stesso:

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

Ho trovato che tutte le risposte su questa pagina avevano ancora problemi. In particolare, ho notato che nessuno di loro avrebbe impedito a IE8 di utilizzare una versione cache della pagina quando vi si accede premendo il pulsante Indietro.

Dopo molte ricerche e test, ho scoperto che le uniche due intestazioni di cui avevo veramente bisogno erano:

Cache-Control: no-store
Vary: *

Per una spiegazione dell’intestazione Vary, consulta http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.6

Su IE6-8, FF1.5-3.5, Chrome 2-3, Safari 4 e Opera 9-10, queste intestazioni hanno causato la richiesta della pagina dal server quando si fa clic su un collegamento alla pagina o si inserisce l’URL direttamente nella barra degli indirizzi. Questo copre circa il 99% di tutti i browser in uso a partire da Jan ’10.

Su IE6 e su Opera 9-10, premendo il pulsante Indietro è ancora ansible caricare la versione memorizzata nella cache. Su tutti gli altri browser che ho provato, hanno recuperato una nuova versione dal server. Finora, non ho trovato alcuna serie di intestazioni che causerà quei browser per non restituire versioni di pagine memorizzate nella cache quando si preme il pulsante Indietro.

Aggiornamento: dopo aver scritto questa risposta, mi sono reso conto che il nostro server web si sta identificando come un server HTTP 1.0. Le intestazioni che ho elencato sono quelle corrette in modo che le risposte da un server HTTP 1.0 non vengano memorizzate nella cache dai browser. Per un server HTTP 1.1, guarda la risposta di BalusC.

Dopo un po ‘di ricerche, abbiamo trovato il seguente elenco di intestazioni che sembrava coprire la maggior parte dei browser:

  • Scadenza : lun, 26 lug 1997 05:00:00 GMT
  • Cache-Control : no-cache , privato, must-revalidate , max-stale = 0, post-check = 0, pre-check = 0 no-store
  • Pragma : no-cache

In ASP.NET abbiamo aggiunto questi utilizzando il seguente frammento:

 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 

Trovato da: http://forums.asp.net/t/1013531.aspx

L’uso dell’intestazione pragma nella risposta è una favola. RFC2616 lo definisce solo come intestazione di richiesta

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

NOTA BENE: Consiglio vivamente di leggere la risposta di @ BalusC. Dopo aver letto il seguente tutorial sul caching: http://www.mnot.net/cache_docs/ (ti consiglio di leggerlo anch’io), credo che sia corretto. Tuttavia, per ragioni storiche (e perché l’ho testato io stesso), includerò la mia risposta originale qui sotto:


Ho provato la risposta “accettata” per PHP, che non ha funzionato per me. Poi ho fatto una piccola ricerca, ho trovato una leggera variante, l’ho testata e ha funzionato. Ecco qui:

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

Questo dovrebbe funzionare Il problema era che quando si imposta la stessa parte dell’intestazione due volte, se il false non viene inviato come secondo argomento della funzione di intestazione, la funzione di intestazione semplicemente sovrascriverà la chiamata header() precedente header() . Quindi, quando si imposta Cache-Control , ad esempio se non si desidera mettere tutti gli argomenti in una chiamata di funzione header() , deve fare qualcosa del genere:

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

Vedi la documentazione più completa qui .

C’è un bug in IE6

Il contenuto di “Content-Encoding: gzip” viene sempre memorizzato nella cache anche se si utilizza “Cache-Control: no-cache”.

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

È ansible disabilitare la compressione gzip per gli utenti IE6 (controllare l’agente utente per “MSIE 6”)

RFC per HTTP 1.1 dice che il metodo corretto è quello di aggiungere un’intestazione HTTP per:

Cache-Control: no-cache

I browser meno recenti potrebbero ignorarlo se non sono adeguatamente conformi a HTTP 1.1. Per quelli puoi provare l’intestazione:

Pragma: no-cache

Questo dovrebbe funzionare anche per i browser HTTP 1.1.

Queste direttive non attenuano alcun rischio per la sicurezza. Esse sono concepite per forzare UA a aggiornare le informazioni volatili, non a mantenere le UA a conservare le informazioni. Vedi questa domanda simile . Per lo meno, non vi è alcuna garanzia che eventuali router, proxy, ecc. Non ignorino le direttive di memorizzazione nella cache.

In una nota più positiva, le politiche riguardanti l’accesso fisico ai computer, l’installazione del software e simili porteranno miglia di vantaggio sulla maggior parte delle aziende in termini di sicurezza. Se i consumatori di queste informazioni sono membri del pubblico, l’unica cosa che puoi veramente fare è aiutarli a capire che una volta che le informazioni raggiungono la loro macchina, quella macchina è la loro responsabilità, non la tua.

La documentazione PHP per la funzione di intestazione ha un esempio piuttosto completo (fornito da una terza parte):

  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 si riscontrano problemi di download con IE6-IE8 su SSL e cache: intestazione no-cache (e valori simili) con i file MS Office è ansible utilizzare la cache: intestazione privata, no-store e file di ritorno su richiesta POST. Funziona.

nel mio caso risolvo il problema in chrome con questo

 

dove ho bisogno di cancellare il contenuto di un precedente modulo dati quando gli utenti fanno clic sul pulsante indietro per motivi di sicurezza

Per ASP.NET Core, crea una semplice class 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 ); } } 

quindi registrarlo con Startup.cs

 app.UseMiddleware(); 

Assicurati di aggiungerlo da qualche parte dopo

 app.UseStaticFiles(); 

L’impostazione dell’intestazione http modificata in una data nel 1995 di solito fa il trucco.

Ecco un esempio:

 Scadenza: mercoledì 15 novembre 1995 04:58:08 GMT
 Ultima modifica: mercoledì 15 novembre 1995 04:58:08 GMT
 Cache-Control: no-cache, must-revalidate

Ho ottenuto risultati migliori e più coerenti su tutti i browser impostando Pragma: no-cache

Le intestazioni nella risposta fornita da BalusC non impediscono a Safari 5 (e probabilmente anche alle versioni precedenti) di visualizzare il contenuto dalla cache del browser quando si utilizza il pulsante Indietro del browser. Un modo per evitare ciò è aggiungere un attributo del gestore di eventi onunload vuoto al tag body:

  

Questo ha apparentemente interrotto la cache di back-forward in Safari: Esiste un evento onload cross-browser quando si fa clic sul pulsante Indietro?

The accepted answer does not appear to work for IIS7+, going by the large number of questions about cache headers not being sent in II7:

  • Something is forcing responses to have cache-control: private in IIS7
  • IIS7: Cache Setting Not Working… why?
  • IIS7 + ASP.NET MVC Client Caching Headers Not Working
  • Set cache-control for aspx pages
  • Cache-control: no-store, must-revalidate not sent to client browser in IIS7 + ASP.NET MVC

And so on

The accepted answer is correct in which headers must be set, but not in how they must be set. This way works with IIS7:

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

The first line sets Cache-control to no-cache , and the second line adds the other attributes no-store, must-revalidate

In addition to the headers consider serving your page via https . Many browsers will not cache https by default.

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

To complete BalusC -> ANSWER If you are using perl you can use CGI to add HTTP headers.

Using Perl:

 Use CGI; sub set_new_query() { binmode STDOUT, ":utf8"; die if defined $query; $query = CGI->new(); print $query->header( -expires => 'Sat, 26 Jul 1997 05:00:00 GMT', -Pragma => 'no-cache', -Cache_Control => join(', ', qw( private no-cache no-store must-revalidate max-age=0 pre-check=0 post-check=0 )) ); } 

Using apache httpd.conf

  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
         provare:
            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.