Comment contrôler la mise en cache des pages Web, sur tous les navigateurs ?
-
09-06-2019 - |
Question
Nos investigations nous ont montré que tous les navigateurs ne respectent pas les directives du cache http de manière uniforme.
Pour des raisons de sécurité nous ne souhaitons pas que certaines pages de notre application soient mises en cache, jamais, par le navigateur Internet.Cela doit fonctionner pour au moins les navigateurs suivants :
- Internet Explorer 6+
- Firefox 1.5+
- Safari 3+
- Opéra 9+
- Chrome
Notre exigence est issue d'un test de sécurité.Après vous être déconnecté de notre site Web, vous pouvez appuyer sur le bouton Précédent et afficher les pages mises en cache.
La solution
Introduction
L'ensemble minimum d'en-têtes correct qui fonctionne sur tous les clients (et proxys) mentionnés :
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0
Le Cache-Control
est conforme à la spécification HTTP 1.1 pour les clients et les proxys (et implicitement requis par certains clients à côté de Expires
).Le Pragma
est conforme à la spécification HTTP 1.0 pour les clients préhistoriques.Le Expires
est conforme aux spécifications HTTP 1.0 et 1.1 pour les clients et les proxys.Dans HTTP 1.1, le Cache-Control
a la priorité sur Expires
, donc après tout, c'est uniquement pour les proxys HTTP 1.0.
Si vous ne vous souciez pas d'IE6 et de sa mise en cache cassée lors de la diffusion de pages via HTTPS avec seulement no-store
, alors vous pourriez omettre Cache-Control: no-cache
.
Cache-Control: no-store, must-revalidate
Pragma: no-cache
Expires: 0
Si vous ne vous souciez pas des clients IE6 ni HTTP 1.0 (HTTP 1.1 a été introduit en 1997), vous pouvez omettre Pragma
.
Cache-Control: no-store, must-revalidate
Expires: 0
Si vous ne vous souciez pas non plus des proxys HTTP 1.0, vous pouvez omettre Expires
.
Cache-Control: no-store, must-revalidate
En revanche, si le serveur inclut automatiquement un Date
en-tête, alors vous pourriez théoriquement omettre Cache-Control
aussi et je compte sur Expires
seulement.
Date: Wed, 24 Aug 2016 18:32:02 GMT
Expires: 0
Mais cela peut échouer si par ex.l'utilisateur final manipule la date du système d'exploitation et le logiciel client s'appuie sur elle.
Autre Cache-Control
paramètres tels que max-age
ne sont pas pertinents si les éléments mentionnés ci-dessus Cache-Control
les paramètres sont spécifiés.Le Last-Modified
en-tête tel qu'inclus dans la plupart des autres réponses, voici seulement intéressant si vous je veux vraiment pour mettre en cache la demande, vous n'avez donc pas besoin de la spécifier du tout.
Comment le régler ?
Utiliser PHP :
header("Cache-Control: no-cache, no-store, must-revalidate"); // HTTP 1.1.
header("Pragma: no-cache"); // HTTP 1.0.
header("Expires: 0"); // Proxies.
Utilisation de 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.
Utilisation d'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.
Utilisation de l'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());
Utilisation d'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.
Utilisation d'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.
Utilisation de 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.
Utilisation de 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.
Utilisation de Python/Pyramide :
request.response.headerlist.extend(
(
('Cache-Control', 'no-cache, no-store, must-revalidate'),
('Pragma', 'no-cache'),
('Expires', '0')
)
)
Utiliser 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.
Utiliser Apache .htaccess
déposer:
<IfModule mod_headers.c>
Header set Cache-Control "no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires 0
</IfModule>
En utilisant 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" />
Balises méta HTML vs en-têtes de réponse HTTP
Il est important de savoir que lorsqu'une page HTML est diffusée via une connexion HTTP et qu'un en-tête est présent dans les deux les en-têtes de réponse HTTP et le HTML <meta http-equiv>
balises, celle spécifiée dans l'en-tête de la réponse HTTP aura la priorité sur la balise méta HTML.La balise méta HTML ne sera utilisée que lorsque la page est affichée à partir du système de fichiers du disque local via un file://
URL.Voir également Chapitre 5.2.2 des spécifications HTML W3.Faites attention lorsque vous ne les spécifiez pas par programme, car le serveur Web peut notamment inclure certaines valeurs par défaut.
En général, tu ferais mieux de simplement pas spécifiez les balises méta HTML pour éviter toute confusion de la part des débutants et comptez sur des en-têtes de réponse HTTP durs.De plus, spécifiquement ceux <meta http-equiv>
les balises sont invalide en HTML5.Seulement le http-equiv
valeurs répertoriées dans Spécification HTML5 sont autorisés.
Vérifier les en-têtes de réponse HTTP réels
Pour vérifier l'un et l'autre, vous pouvez les voir/déboguer dans le moniteur de trafic HTTP de l'ensemble d'outils de développement du navigateur Web.Vous pouvez y accéder en appuyant sur F12 dans Chrome/Firefox23+/IE9+, puis en ouvrant le panneau d'onglets « Réseau » ou « Net », puis en cliquant sur la requête HTTP qui vous intéresse pour découvrir tous les détails sur la requête et la réponse HTTP.Le ci-dessous capture d'écran vient de Chrome :
Je souhaite également définir ces en-têtes sur les téléchargements de fichiers
Tout d'abord, cette question et réponse cible les « pages Web » (pages HTML), et non les « téléchargements de fichiers » (PDF, zip, Excel, etc.).Vous feriez mieux de les mettre en cache et d'utiliser un identifiant de version de fichier quelque part dans le chemin URI ou la chaîne de requête pour forcer un nouveau téléchargement sur un fichier modifié.De toute façon, lorsque vous appliquez ces en-têtes sans cache sur les téléchargements de fichiers, méfiez-vous du bogue IE7/8 lors du téléchargement d'un fichier via HTTPS au lieu de HTTP.Pour plus de détails, voir IE ne peut pas télécharger foo.jsf.IE n'a pas pu ouvrir ce site Internet.Le site demandé est soit indisponible, soit introuvable.
Autres conseils
(Salut tout le monde:s'il vous plaît, ne copiez pas et collez sans réfléchir tous les en-têtes que vous pouvez trouver)
Tout d'abord, L'historique du bouton Retour est pas une cache:
Le modèle de fraîcheur (Section 4.2) ne s’applique pas nécessairement aux mécanismes historiques.Autrement dit, un mécanisme d'historique peut afficher une représentation précédente même si elle a expiré.
Dans l'ancienne spécification HTTP, la formulation était encore plus forte, indiquant explicitement aux navigateurs d'ignorer les directives de cache pour l'historique du bouton de retour.
Back est censé remonter le temps (jusqu'au moment où l'utilisateur était connecté).Il ne navigue pas vers une URL précédemment ouverte.
Cependant, en pratique, le cache peut influencer le bouton retour, dans des circonstances bien précises :
- Page doit être livré HTTPS, sinon ce contournement du cache ne sera pas fiable.De plus, si vous n'utilisez pas HTTPS, votre page est vulnérable au vol de connexion de nombreuses autres manières.
- Vous devez envoyer
Cache-Control: no-store, must-revalidate
(certains navigateurs observentno-store
et certains observentmust-revalidate
)
Toi jamais besoin de :
<meta>
avec les en-têtes de cache - cela ne fonctionne pas du tout.Totalement inutile.post-check
/pre-check
- c'est une directive uniquement IE qui s'applique uniquement à pouvant être mis en cache ressources.- Envoi du même en-tête deux fois ou en douzaine de parties.Certains extraits PHP remplacent en fait les en-têtes précédents, ce qui entraîne l'envoi du dernier seul.
Si vous le souhaitez, vous pouvez ajouter :
no-cache
oumax-age=0
, ce qui rendra la ressource (URL) « obsolète » et obligera les navigateurs à vérifier auprès du serveur s'il existe une version plus récente (no-store
cela implique déjà cela encore plus fort).Expires
avec une date dans le passé pour les clients HTTP/1.0 (bien que réel Les clients HTTP/1.0 uniquement sont totalement inexistants de nos jours).
Comme l'a dit pornoleL, ce que vous voulez n'est pas désactiver le cache, mais désactiver le tampon historique.Différents navigateurs ont leurs propres méthodes subtiles pour désactiver le tampon d'historique.
Dans Chrome (v28.0.1500.95 m), nous ne pouvons le faire qu'en Cache-Control: no-store
.
Dans FireFox (v23.0.1), l'un de ces éléments fonctionnera :
Cache-Control: no-store
Cache-Control: no-cache
(https uniquement)Pragma: no-cache
(https uniquement)Vary: *
(https uniquement)
Dans Opera (v12.15), nous ne pouvons le faire qu'en Cache-Control: must-revalidate
(https uniquement).
Dans Safari (v5.1.7, 7534.57.2), l'un de ces éléments fonctionnera :
Cache-Control: no-store
<body onunload="">
en HTMLCache-Control: no-store
(https uniquement)
Dans IE8 (v8.0.6001.18702IC), l'un de ces éléments fonctionnera :
Cache-Control: must-revalidate, max-age=0
Cache-Control: no-cache
Cache-Control: no-store
Cache-Control: must-revalidate
Expires: 0
Cache-Control: must-revalidate
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
(https uniquement)Vary: *
(https uniquement)
La combinaison de ce qui précède nous donne cette solution qui fonctionne pour Chrome 28, FireFox 23, IE8, Safari 5.1.7 et Opera 12.15 : Cache-Control: no-store, must-revalidate
(https uniquement)
Notez que https est nécessaire car Opera ne désactiverait pas le tampon d'historique pour les pages http simples.Si vous ne pouvez vraiment pas obtenir https et que vous êtes prêt à ignorer Opera, le mieux que vous puissiez faire est ceci :
Cache-Control: no-store
<body onunload="">
Ci-dessous montre les journaux bruts de mes tests :
HTTP :
Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
<body onunload="">
Échouer:Opéra 12h15
Succès:Chrome 28, FireFox 23, IE8, Safari 5.1.7Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
Vary: *
<body onunload="">
Échouer:Opéra 12h15
Succès:Chrome 28, FireFox 23, IE8, Safari 5.1.7Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
Échouer:Safari 5.1.7, Opéra 12.15
Succès:Chrome 28, FireFox 23, IE8Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
Vary: *
Échouer:Safari 5.1.7, Opéra 12.15
Succès:Chrome 28, FireFox 23, IE8Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
<body onunload="">
Échouer:Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Succès:IE8Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
Vary: *
<body onunload="">
Échouer:Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Succès:IE8Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
<body onunload="">
Échouer:Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Succès:IE8Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
Vary: *
<body onunload="">
Échouer:Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Succès:IE8Cache-Control: no-store
Échouer:Safari 5.1.7, Opéra 12.15
Succès:Chrome 28, FireFox 23, IE8Cache-Control: no-store
<body onunload="">
Échouer:Opéra 12h15
Succès:Chrome 28, FireFox 23, IE8, Safari 5.1.7Cache-Control: no-cache
Échouer:Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Succès:IE8Vary: *
Échouer:Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
Succès:aucunPragma: no-cache
Échouer:Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
Succès:aucunCache-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="">
Échouer:Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Succès:IE8Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
<body onunload="">
Échouer:Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Succès:IE8Cache-Control: must-revalidate, max-age=0
Échouer:Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Succès:IE8Cache-Control: must-revalidate
Expires: 0
Échouer:Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Succès:IE8Cache-Control: must-revalidate
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Échouer:Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Succès:IE8Cache-Control: private, must-revalidate, proxy-revalidate, s-maxage=0
Pragma: no-cache
Vary: *
<body onunload="">
Échouer:Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
Succès:aucun
HTTPS :
Cache-Control: private, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
<body onunload="">
Échouer:Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
Succès:aucunCache-Control: private, max-age=0, proxy-revalidate, s-maxage=0
Expires: Sat, 12 Oct 1991 05:00:00 GMT
<body onunload="">
Échouer:Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
Succès:aucunVary: *
Échouer:Chrome 28, Safari 5.1.7, Opéra 12.15
Succès:FireFox 23, IE8Pragma: no-cache
Échouer:Chrome 28, Safari 5.1.7, Opéra 12.15
Succès:FireFox 23, IE8Cache-Control: no-cache
Échouer:Chrome 28, Safari 5.1.7, Opéra 12.15
Succès:FireFox 23, IE8Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
Échouer:Chrome 28, Safari 5.1.7, Opéra 12.15
Succès:FireFox 23, IE8Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
Échouer:Chrome 28, Safari 5.1.7, Opéra 12.15
Succès:FireFox 23, IE8Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
Vary: *
Échouer:Chrome 28, Safari 5.1.7, Opéra 12.15
Succès:FireFox 23, IE8Cache-Control: must-revalidate
Échouer:Chrome 28, FireFox 23, IE8, Safari 5.1.7
Succès:Opéra 12h15Cache-Control: private, must-revalidate, proxy-revalidate, s-maxage=0
<body onunload="">
Échouer:Chrome 28, FireFox 23, IE8, Safari 5.1.7
Succès:Opéra 12h15Cache-Control: must-revalidate, max-age=0
Échouer:Chrome 28, FireFox 23, Safari 5.1.7
Succès:IE8, Opéra 12.15Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
Vary: *
<body onunload="">
Échouer:Chrome 28, Safari 5.1.7
Succès:FireFox 23, IE8, Opera 12.15Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
<body onunload="">
Échouer:Chrome 28, Safari 5.1.7
Succès:FireFox 23, IE8, Opera 12.15Cache-Control: no-store
Échouer:Opéra 12h15
Succès:Chrome 28, FireFox 23, IE8, Safari 5.1.7Cache-Control: private, no-cache, no-store, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
<body onunload="">
Échouer:Opéra 12h15
Succès:Chrome 28, FireFox 23, IE8, Safari 5.1.7Cache-Control: private, no-cache, no-store, max-age=0, proxy-revalidate, s-maxage=0
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
Vary: *
<body onunload="">
Échouer:Opéra 12h15
Succès:Chrome 28, FireFox 23, IE8, Safari 5.1.7Cache-Control: private, no-cache
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
Vary: *
Échouer:Chrome 28, Safari 5.1.7, Opéra 12.15
Succès:FireFox 23, IE8Cache-Control: must-revalidate
Expires: 0
Échouer:Chrome 28, FireFox 23, Safari 5.1.7,
Succès:IE8, Opéra 12.15Cache-Control: must-revalidate
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Échouer:Chrome 28, FireFox 23, Safari 5.1.7,
Succès:IE8, Opéra 12.15Cache-Control: private, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
<body onunload="">
Échouer:Chrome 28, FireFox 23, Safari 5.1.7,
Succès:IE8, Opéra 12.15Cache-Control: private, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: Sat, 12 Oct 1991 05:00:00 GMT
<body onunload="">
Échouer:Chrome 28, FireFox 23, Safari 5.1.7,
Succès:IE8, Opéra 12.15Cache-Control: private, must-revalidate
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
Vary: *
Échouer:Chrome 28, Safari 5.1.7
Succès:FireFox 23, IE8, Opera 12.15Cache-Control: no-store, must-revalidate
Échouer:aucun
Succès:Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
J'ai trouvé la route web.config utile (j'ai essayé de l'ajouter à la réponse mais ne semble pas avoir été acceptée, je la publie donc ici)
<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>
Et voici la manière express/node.js de faire de même :
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();
});
J'ai trouvé que toutes les réponses sur cette page posaient encore des problèmes.En particulier, j'ai remarqué qu'aucun d'entre eux n'empêcherait IE8 d'utiliser une version mise en cache de la page lorsque vous y accédiez en appuyant sur le bouton Précédent.
Après de nombreuses recherches et tests, j'ai découvert que les deux seuls en-têtes dont j'avais réellement besoin étaient :
Contrôle du cache :sans magasin
Varier:*
Pour une explication de l'en-tête Vary, consultez http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.6
Sur IE6-8, FF1.5-3.5, Chrome 2-3, Safari 4 et Opera 9-10, ces en-têtes provoquaient la demande de la page auprès du serveur lorsque vous cliquez sur un lien vers la page ou que vous insérez l'URL. directement dans la barre d'adresse.Cela couvre environ 99% de tous les navigateurs utilisés en janvier 2010.
Sur IE6 et Opera 9-10, appuyer sur le bouton Précédent provoquait toujours le chargement de la version mise en cache.Sur tous les autres navigateurs que j'ai testés, ils ont récupéré une nouvelle version du serveur.Jusqu'à présent, je n'ai trouvé aucun ensemble d'en-têtes qui empêcheraient ces navigateurs de renvoyer les versions mises en cache des pages lorsque vous appuyez sur le bouton Précédent.
Mise à jour: Après avoir écrit cette réponse, j'ai réalisé que notre serveur Web s'identifie comme un serveur HTTP 1.0.Les en-têtes que j'ai répertoriés sont les bons pour que les réponses d'un serveur HTTP 1.0 ne soient pas mises en cache par les navigateurs.Pour un serveur HTTP 1.1, regardez celui de BalusC répondre.
Après quelques recherches, nous avons abouti à la liste d'en-têtes suivante qui semble couvrir la plupart des navigateurs :
- Expire:Lun. 26 juillet 1997 05:00:00 GMT
- Contrôle du cache: sans cache, privé, il faut revalider, max-stale=0, post-check=0, pre-check=0 sans magasin
- Pragma:sans cache
Dans ASP.NET, nous les avons ajoutés à l'aide de l'extrait suivant :
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
Trouvé à partir de : http://forums.asp.net/t/1013531.aspx
L'utilisation de l'en-tête pragma dans la réponse est une histoire d'épouses.La RFC2616 le définit uniquement comme en-tête de requête
CLAUSE DE NON-RESPONSABILITÉ:Je suggère fortement de lire la réponse de @BalusC.Après avoir lu le tutoriel de mise en cache suivant : http://www.mnot.net/cache_docs/ (Je vous recommande de le lire aussi), je pense que c'est correct.Cependant, pour des raisons historiques (et parce que je l'ai testé moi-même), j'inclurai ma réponse originale ci-dessous :
J'ai essayé la réponse « acceptée » pour PHP, qui n'a pas fonctionné pour moi.Ensuite, j’ai fait quelques recherches, j’ai trouvé une légère variante, je l’ai testée et cela a fonctionné.C'est ici:
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');
Cela devrait fonctionner.Le problème était que lorsque l'on définissait deux fois la même partie de l'en-tête, si le false
n'est pas envoyé comme deuxième argument à la fonction d'en-tête, la fonction d'en-tête écrasera simplement le précédent header()
appel.Ainsi, lors du réglage du Cache-Control
, par exemple si on ne veut pas mettre tous les arguments en un seul header()
appel de fonction, il doit faire quelque chose comme ceci :
header('Cache-Control: this');
header('Cache-Control: and, this', false);
Voir une documentation plus complète ici.
Il y a un bug dans IE6
Contenu avec « Content-Encoding :gzip" est toujours mis en cache même si vous utilisez "Cache-Control :sans cache".
http://support.microsoft.com/kb/321722
Vous pouvez désactiver la compression gzip pour les utilisateurs d'IE6 (vérifiez l'agent utilisateur pour "MSIE 6")
Pour ASP.NET Core, créez une classe middleware simple :
public class NoCacheMiddleware
{
private readonly RequestDelegate m_next;
public NoCacheMiddleware( RequestDelegate next )
{
m_next = next;
}
public async Task Invoke( HttpContext httpContext )
{
httpContext.Response.OnStarting( ( state ) =>
{
// ref: http://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 );
}
}
puis enregistrez-le avec Startup.cs
app.UseMiddleware<NoCacheMiddleware>();
Assurez-vous de l'ajouter quelque part après
app.UseStaticFiles();
La RFC pour HTTP1.1 indique que la méthode appropriée consiste à ajouter un en-tête HTTP pour :
Contrôle du cache :sans cache
Les navigateurs plus anciens peuvent ignorer cela s'ils ne sont pas correctement conformes à HTTP 1.1.Pour ceux-là, vous pouvez essayer l'en-tête :
Pragme :sans cache
Ceci est également censé fonctionner pour les navigateurs HTTP 1.1.
Ces directives n’atténuent aucun risque de sécurité.Ils visent en réalité à forcer les UA à actualiser les informations volatiles, et non à les empêcher de conserver des informations.Voir cette question similaire.À tout le moins, il n'y a aucune garantie que les routeurs, proxys, etc.n'ignorera pas non plus les directives de mise en cache.
Sur une note plus positive, les politiques concernant l'accès physique aux ordinateurs, l'installation de logiciels, etc. vous donneront une longueur d'avance sur la plupart des entreprises en termes de sécurité.Si les consommateurs de ces informations sont des membres du public, la seule chose que vous pouvez réellement faire est de les aider à comprendre qu'une fois que les informations arrivent sur leur machine, cette machine est leur responsabilité, pas la vôtre.
Définir l'en-tête http modifié à une date en 1995 fait généralement l'affaire.
Voici un exemple :
Expires: Wed, 15 Nov 1995 04:58:08 GMT Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT Cache-Control: no-cache, must-revalidate
Le Documentation PHP pour la fonction d'en-tête a un exemple assez complet (contribué par un tiers):
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);
Si vous rencontrez des problèmes de téléchargement avec IE6-IE8 via SSL et l'en-tête cache:no-cache (et valeurs similaires) avec les fichiers MS Office, vous pouvez utiliser l'en-tête cache:private,no-store et renvoyer le fichier sur demande POST.Ça marche.
dans mon cas, je résous le problème dans Chrome avec ceci
<form id="form1" runat="server" autocomplete="off">
où je dois effacer le contenu des données d'un formulaire précédent lorsque les utilisateurs cliquent sur le bouton Retour pour des raisons de sécurité
J'ai eu les meilleurs résultats et les plus cohérents dans tous les navigateurs en définissant Pragma:sans cache
Les en-têtes de la réponse fournie par BalusC n'empêchent pas Safari 5 (et éventuellement les versions plus anciennes) d'afficher le contenu du cache du navigateur lors de l'utilisation du bouton Précédent du navigateur.Un moyen d'éviter cela consiste à ajouter un attribut de gestionnaire d'événement onunload vide à la balise body :
<body onunload="">
Ce hack casse apparemment le cache arrière dans Safari : Y a-t-il un événement de chargement entre navigateurs lorsque vous cliquez sur le bouton Précédent ?
La réponse acceptée ne semble pas fonctionner pour IIS7+, compte tenu du grand nombre de questions sur les en-têtes de cache non envoyés dans II7 :
- Quelque chose oblige les réponses à contrôler le cache :privé dans IIS7
- IIS7 :Le paramètre de cache ne fonctionne pas...pourquoi ?
- Les en-têtes de mise en cache du client IIS7 + ASP.NET MVC ne fonctionnent pas
- Définir le contrôle du cache pour les pages ASPX
- Contrôle du cache :no-store, doit-revalider non envoyé au navigateur client dans IIS7 + ASP.NET MVC
Et ainsi de suite
La réponse acceptée est correcte quant à la définition des en-têtes, mais pas à la manière dont ils doivent être définis.Cette méthode fonctionne avec IIS7 :
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.AppendCacheExtension("no-store, must-revalidate");
Response.AppendHeader("Pragma", "no-cache");
Response.AppendHeader("Expires", "-1");
Les ensembles de première ligne Cache-control
à no-cache
, et la deuxième ligne ajoute les autres attributs no-store, must-revalidate
Aussi, juste pour faire bonne mesure, assurez-vous de réinitialiser le ExpiresDefault
dans ton .htaccess
fichier si vous l'utilisez pour activer la mise en cache.
ExpiresDefault "access plus 0 seconds"
Ensuite, vous pouvez utiliser ExpiresByType
pour définir des valeurs spécifiques pour les fichiers que vous souhaitez mettre en cache :
ExpiresByType image/x-icon "access plus 3 month"
Cela peut également s'avérer utile si vos fichiers dynamiques, par ex.php, etcsont mis en cache par le navigateur et vous ne comprenez pas pourquoi.Vérifier ExpiresDefault
.
En plus des en-têtes, pensez à diffuser votre page via https.De nombreux navigateurs ne mettront pas https en cache par défaut.
//In .net MVC
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public ActionResult FareListInfo(long id)
{
}
// In .net webform
<%@ OutputCache NoStore="true" Duration="0" VaryByParam="*" %>
Compléter BalusC -> RÉPONDRESi vous utilisez Perl, vous pouvez utiliser CGI pour ajouter des en-têtes HTTP.
Utilisation de 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
))
);
}
Utiliser Apache httpd.conf
<FilesMatch "\.(html|htm|js|css|pl)$">
FileETag None
<ifModule mod_headers.c>
Header unset ETag
Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
</ifModule>
Note: Lorsque j'ai essayé d'utiliser le META HTML, les navigateurs les ont ignorés et ont mis la page en cache.
Je veux juste souligner que si quelqu'un souhaite empêcher la mise en cache UNIQUEMENT du contenu dynamique, l'ajout de ces en-têtes supplémentaires doit être effectué par programme.
J'ai modifié le fichier de configuration de mon projet pour ajouter des en-têtes sans cache, mais cela a également désactivé la mise en cache du contenu statique, ce qui n'est généralement pas souhaitable.La modification des en-têtes de réponse dans le code garantit que les images et les fichiers de style seront mis en cache.
C’est assez évident, mais cela mérite néanmoins d’être mentionné.
Et une autre mise en garde.Soyez prudent en utilisant la méthode ClearHeaders de la classe HttpResponse.Cela peut vous donner des bleus si vous l’utilisez de manière imprudente.Comme ça me l'a donné.
Après la redirection sur l'événement ActionFilterAttribute, les conséquences de la suppression de tous les en-têtes sont la perte de toutes les données de session et des données dans le stockage TempData.Il est plus sûr de rediriger à partir d'une action ou de ne pas effacer les en-têtes lorsque la redirection est en cours.
Après réflexion, je déconseille à tous d’utiliser la méthode ClearHeaders.Il est préférable de supprimer les en-têtes séparément.Et pour définir correctement l'en-tête Cache-Control, j'utilise ce code :
filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
filterContext.HttpContext.Response.Cache.AppendCacheExtension("no-store, must-revalidate");
je n'ai pas eu de chance avec <head><meta>
éléments.L'ajout direct de paramètres liés au cache HTTP (en dehors de la documentation HTML) fonctionne effectivement pour moi.
Exemple de code en Python utilisant web.py web.header
les appels suivent.J'ai délibérément rédigé mon code utilitaire personnel non pertinent.
import web import sys import PERSONAL-UTILITIES myname = "main.py" urls = ( '/', 'main_class' ) main = web.application(urls, globals()) render = web.template.render("templates/", base="layout", cache=False) class main_class(object): def GET(self): web.header("Cache-control","no-cache, no-store, must-revalidate") web.header("Pragma", "no-cache") web.header("Expires", "0") return render.main_form() def POST(self): msg = "POSTed:" form = web.input(function = None) web.header("Cache-control","no-cache, no-store, must-revalidate") web.header("Pragma", "no-cache") web.header("Expires", "0") return render.index_laid_out(greeting = msg + form.function) if __name__ == "__main__": nargs = len(sys.argv) # Ensure that there are enough arguments after python program name if nargs != 2: LOG-AND-DIE("%s: Command line error, nargs=%s, should be 2", myname, nargs) # Make sure that the TCP port number is numeric try: tcp_port = int(sys.argv[1]) except Exception as e: LOG-AND-DIE ("%s: tcp_port = int(%s) failed (not an integer)", myname, sys.argv[1]) # All is well! JUST-LOG("%s: Running on port %d", myname, tcp_port) web.httpserver.runsimple(main.wsgifunc(), ("localhost", tcp_port)) main.run()
Voir ce lien vers une étude de cas sur la mise en cache :
http://securityevaluators.com/knowledge/case_studies/caching/
Résumé, selon l'article, seulement Cache-Control: no-store
fonctionne sur Chrome, Firefox et IE.IE accepte d'autres contrôles, mais pas Chrome et Firefox.Le lien est une bonne lecture complète avec l'historique de la mise en cache et la documentation de la preuve de concept.