Как мы контролируем кэширование веб-страниц во всех браузерах?
Наши исследования показали, что не все браузеры одинаково уважают директивы кеша HTTP.
По соображениям безопасности мы не хотим, некоторые страницы в нашем приложении для кэширования, когда - либо, с помощью веб - браузера. Это должно работать как минимум для следующих браузеров:
- Internet Explorer 6+
- Firefox 1. 5+
- Сафари 3+
- Опера 9+
- Хром
Наше требование пришло из теста безопасности. После выхода из нашего веб-сайта вы можете нажать кнопку "Назад" и просмотреть кэшированные страницы.
Ответы
Ответ 1
Вступление
Правильный минимальный набор заголовков, который работает на всех упомянутых клиентах (и прокси):
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0
Cache-Control
соответствует спецификации HTTP 1.1 для клиентов и прокси-серверов (и неявно требуется для некоторых клиентов, следующих за Expires
). Pragma
соответствует спецификации HTTP 1.0 для доисторических клиентов. Expires
соответствует спецификациям HTTP 1.0 и 1.1 для клиентов и прокси. В HTTP 1.1 Cache-Control
имеет приоритет над Expires
, так что он в конце концов только для прокси HTTP 1.0.
Если вас не волнует IE6 и его неправильное кэширование при обслуживании страниц по HTTPS только no-store
, то вы можете опустить Cache-Control: no-cache
.
Cache-Control: no-store, must-revalidate
Pragma: no-cache
Expires: 0
Если вас не интересуют ни IE6, ни клиенты HTTP 1.0 (HTTP 1.1 был представлен в 1997 году), вы можете опустить Pragma
.
Cache-Control: no-store, must-revalidate
Expires: 0
Если вам не нужны прокси-серверы HTTP 1.0, вы можете опустить Expires
.
Cache-Control: no-store, must-revalidate
С другой стороны, если сервер автоматически включает в себя действительный заголовок Date
, то теоретически вы можете также опустить Cache-Control
и полагаться только на Expires
.
Date: Wed, 24 Aug 2016 18:32:02 GMT
Expires: 0
Но это может не сработать, если, например, конечный пользователь манипулирует датой операционной системы и клиентское программное обеспечение полагается на нее.
Другие параметры Cache-Control
такие как max-age
, не имеют значения, если указаны вышеупомянутые параметры Cache-Control
. Заголовок Last-Modified
включенный в большинство других ответов, интересен только в том случае, если вы действительно хотите кэшировать запрос, поэтому вам вообще не нужно его указывать.
Как это установить?
Используя PHP:
header("Cache-Control: no-cache, no-store, must-revalidate"); // HTTP 1.1.
header("Pragma: no-cache"); // HTTP 1.0.
header("Expires: 0"); // Proxies.
Используя Java-сервлет или 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.
Использование 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.
Использование ASP.NET Web API:
// '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());
Использование 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.
Используя 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.
Используя Ruby on Rails или 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.
Использование 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.
Использование Python/Pyramid:
request.response.headerlist.extend(
(
('Cache-Control', 'no-cache, no-store, must-revalidate'),
('Pragma', 'no-cache'),
('Expires', '0')
)
)
Используя 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.
Используя Apache .htaccess
файл:
<IfModule mod_headers.c>
Header set Cache-Control "no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires 0
</IfModule>
Использование HTML4:
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
Метатеги HTML и заголовки ответа HTTP
Важно знать, что когда HTML-страница обслуживается через соединение HTTP и заголовок присутствует как в заголовках ответа HTTP, так и в <meta http-equiv>
HTML <meta http-equiv>
, то тот, который указан в заголовке ответа HTTP, получит приоритет над метатегом HTML. Метатег HTML будет использоваться только при просмотре страницы из файловой системы локального диска через file://
URL. Смотрите также W3 HTML spec глава 5.2.2. Будьте осторожны, когда вы не указываете их программно, потому что веб-сервер может включать некоторые значения по умолчанию.
Как правило, лучше не указывать метатеги HTML, чтобы избежать путаницы среди начинающих, и полагаться на жесткие заголовки HTTP-ответов. Более того, именно эти теги <meta http-equiv>
недопустимы в HTML5. Разрешены только значения http-equiv
указанные в спецификации HTML5.
Проверка фактических заголовков ответа HTTP
Чтобы проверить и то, и другое, вы можете увидеть/отладить их в мониторе HTTP-трафика набора инструментов разработчика веб-браузера. Это можно сделать, нажав F12 в Chrome/Firefox23+/IE9 +, а затем открыв панель вкладок "Сеть" или "Сеть", а затем щелкнув интересующий HTTP-запрос, чтобы раскрыть все подробности о HTTP-запросе и ответе. Ниже приведен скриншот из Chrome:
Я хочу установить эти заголовки и при загрузке файлов
Прежде всего, этот вопрос и ответ нацелены на "веб-страницы" (HTML-страницы), а не на "загрузки файлов" (PDF, zip, Excel и т.д.). Вам лучше кэшировать их и использовать некоторый идентификатор версии файла где-нибудь в пути URI или строку запроса, чтобы принудительно выполнить повторную загрузку измененного файла. В любом случае, применяя эти заголовки без кэширования к загрузке файлов, остерегайтесь ошибки IE7/8 при обработке загрузки файлов по HTTPS вместо HTTP. Подробнее см. IE не может загрузить foo.jsf. IE не смог открыть этот интернет-сайт. Запрашиваемый сайт либо недоступен, либо не найден.
Ответ 2
(эй, все: пожалуйста, не просто бездумно скопируйте и вставьте все заголовки, которые вы можете найти)
Прежде всего, История кнопки "Назад" не является кешем:
Модель свежести (раздел 4.2) не обязательно относится к механизмам истории. То есть, механизм истории может отображать предыдущее представление, даже если оно истекло.
В старой спецификации HTTP формулировка была еще более сильной, явно говоря обозревателям игнорировать директивы кэша для истории кнопок.
Возврат должен возвращаться во времени (до момента входа пользователя в систему). Он не перемещается вперед к ранее открытому URL-адресу.
Однако на практике кеш может влиять на кнопку "Назад" в особых обстоятельствах:
- Страница должна быть доставлена через HTTPS, в противном случае это переполнение кэша не будет надежным. Кроме того, если вы не используете HTTPS, ваша страница уязвима для воровства входа во многих других целях.
- Вы должны отправить
Cache-Control: no-store, must-revalidate
(некоторые браузеры наблюдают no-store
, а некоторые наблюдают must-revalidate
)
Вам никогда не понадобится:
-
<meta>
с заголовками кеша - он вообще не работает. Совершенно бесполезно.
-
post-check
/pre-check
- это директива только для IE, которая применяется только к кэшируемым ресурсам.
- Отправка одного и того же заголовка дважды или десятка частей. Некоторые фрагменты PHP фактически заменяют предыдущие заголовки, в результате чего отправляется только последний.
Если вы хотите, вы можете добавить:
-
no-cache
или max-age=0
, что сделает ресурс (URL) "устаревшим" и потребует от браузеров проверки с сервером, если более новая версия (no-store
уже подразумевает это еще сильнее).
-
Expires
с датой в прошлом для клиентов HTTP/1.0 (хотя настоящие клиенты HTTP/1.0 полностью не существуют в наши дни).
Бонус: Новый HTTP-кеширующий RFC.
Ответ 3
Как заявила porneL, вы хотите не деактивировать кеш, а деактивировать буфер истории. У разных браузеров есть свои тонкие способы отключить буфер истории.
В Chrome (v28.0.1500.95 м) мы можем сделать это только Cache-Control: no-store
.
В FireFox (v23.0.1) любой из них будет работать:
В Opera (v12.15) мы можем сделать это только с помощью Cache-Control: must-revalidate
(только https).
В Safari (v5.1.7, 7534.57.2) любой из них будет работать:
В IE8 (v8.0.6001.18702IC) любой из них будет работать:
-
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)
-
Vary: *
(только https)
Сочетание вышеописанного дает нам это решение, которое работает для Chrome 28, FireFox 23, IE8, Safari 5.1.7 и Opera 12.15: Cache-Control: no-store, must-revalidate
(только https)
Обратите внимание, что требуется https, потому что Opera не будет деактивировать буфер истории для простых страниц http. Если вы действительно не можете получить https, и вы готовы игнорировать Opera, самое лучшее, что вы можете сделать, это следующее:
Cache-Control: no-store
<body onunload="">
Ниже показаны исходные журналы моих тестов:
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="">
Ошибка: Opera 12.15
Успех: Chrome 28, FireFox 23, IE8, Safari 5.1.7
-
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="">
Ошибка: Opera 12.15
Успех: Chrome 28, FireFox 23, IE8, Safari 5.1.7
-
Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
Сбой: Safari 5.1.7, Opera 12.15
Успех: Chrome 28, FireFox 23, IE8
-
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: *
Сбой: Safari 5.1.7, Opera 12.15
Успех: Chrome 28, FireFox 23, IE8
-
Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
<body onunload="">
Сбой: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Успех: IE8
-
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="">
Сбой: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Успех: IE8
-
Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
<body onunload="">
Сбой: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Успех: IE8
-
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="">
Сбой: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Успех: IE8
-
Cache-Control: no-store
Сбой: Safari 5.1.7, Opera 12.15
Успех: Chrome 28, FireFox 23, IE8
-
Cache-Control: no-store
<body onunload="">
Ошибка: Opera 12.15
Успех: Chrome 28, FireFox 23, IE8, Safari 5.1.7
-
Cache-Control: no-cache
Сбой: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Успех: IE8
-
Vary: *
Ошибка: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
Успех: none
-
Pragma: no-cache
Ошибка: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
Успех: none
-
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="">
Сбой: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Успех: IE8
-
Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
<body onunload="">
Сбой: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Успех: IE8
-
Cache-Control: must-revalidate, max-age=0
Сбой: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Успех: IE8
-
Cache-Control: must-revalidate
Expires: 0
Сбой: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Успех: IE8
-
Cache-Control: must-revalidate
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Сбой: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
Успех: IE8
-
Cache-Control: private, must-revalidate, proxy-revalidate, s-maxage=0
Pragma: no-cache
Vary: *
<body onunload="">
Ошибка: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
Успех: none
HTTPS:
-
Cache-Control: private, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
<body onunload="">
Ошибка: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
Успех: none
-
Cache-Control: private, max-age=0, proxy-revalidate, s-maxage=0
Expires: Sat, 12 Oct 1991 05:00:00 GMT
<body onunload="">
Ошибка: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
Успех: none
-
Vary: *
Ошибка: Chrome 28, Safari 5.1.7, Opera 12.15
Успех: FireFox 23, IE8
-
Pragma: no-cache
Ошибка: Chrome 28, Safari 5.1.7, Opera 12.15
Успех: FireFox 23, IE8
-
Cache-Control: no-cache
Ошибка: Chrome 28, Safari 5.1.7, Opera 12.15
Успех: FireFox 23, IE8
-
Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
Ошибка: Chrome 28, Safari 5.1.7, Opera 12.15
Успех: FireFox 23, IE8
-
Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
Ошибка: Chrome 28, Safari 5.1.7, Opera 12.15
Успех: FireFox 23, IE8
-
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: *
Ошибка: Chrome 28, Safari 5.1.7, Opera 12.15
Успех: FireFox 23, IE8
-
Cache-Control: must-revalidate
Ошибка: Chrome 28, FireFox 23, IE8, Safari 5.1.7
Успех: Opera 12.15
-
Cache-Control: private, must-revalidate, proxy-revalidate, s-maxage=0
<body onunload="">
Ошибка: Chrome 28, FireFox 23, IE8, Safari 5.1.7
Успех: Opera 12.15
-
Cache-Control: must-revalidate, max-age=0
Ошибка: Chrome 28, FireFox 23, Safari 5.1.7
Успех: IE8, Opera 12.15
-
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="">
Ошибка: Chrome 28, Safari 5.1.7
Успех: FireFox 23, IE8, Opera 12.15
-
Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
<body onunload="">
Ошибка: Chrome 28, Safari 5.1.7
Успех: FireFox 23, IE8, Opera 12.15
-
Cache-Control: no-store
Ошибка: Opera 12.15
Успех: Chrome 28, FireFox 23, IE8, Safari 5.1.7
-
Cache-Control: private, no-cache, no-store, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
Pragma: no-cache
Vary: *
<body onunload="">
Ошибка: Opera 12.15
Успех: Chrome 28, FireFox 23, IE8, Safari 5.1.7
-
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="">
Ошибка: Opera 12.15
Успех: Chrome 28, FireFox 23, IE8, Safari 5.1.7
-
Cache-Control: private, no-cache
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
Vary: *
Ошибка: Chrome 28, Safari 5.1.7, Opera 12.15
Успех: FireFox 23, IE8
-
Cache-Control: must-revalidate
Expires: 0
Ошибка: Chrome 28, FireFox 23, Safari 5.1.7,
Успех: IE8, Opera 12.15
-
Cache-Control: must-revalidate
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Ошибка: Chrome 28, FireFox 23, Safari 5.1.7,
Успех: IE8, Opera 12.15
-
Cache-Control: private, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: 0
<body onunload="">
Ошибка: Chrome 28, FireFox 23, Safari 5.1.7,
Успех: IE8, Opera 12.15
-
Cache-Control: private, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
Expires: Sat, 12 Oct 1991 05:00:00 GMT
<body onunload="">
Ошибка: Chrome 28, FireFox 23, Safari 5.1.7,
Успех: IE8, Opera 12.15
-
Cache-Control: private, must-revalidate
Expires: Sat, 12 Oct 1991 05:00:00 GMT
Pragma: no-cache
Vary: *
Ошибка: Chrome 28, Safari 5.1.7
Успех: FireFox 23, IE8, Opera 12.15
-
Cache-Control: no-store, must-revalidate
Fail: none
Успех: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
Ответ 4
Я нашел полезный маршрут web.config(попытался добавить его в ответ, но, похоже, не был принят таким образом, размещая здесь)
<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>
А вот способ express/ node.js сделать то же самое:
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();
});
Ответ 5
Я обнаружил, что у всех ответов на этой странице все еще были проблемы. В частности, я заметил, что ни один из них не помешает IE8 использовать кэшированную версию страницы, когда вы открыли ее, нажав кнопку "Назад".
После долгих исследований и испытаний я обнаружил, что мне нужны только два заголовка:
Cache-Control: нет магазина
Варь: *
Для объяснения заголовка Vary, посмотрите http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.6
В IE6-8, FF1.5-3.5, Chrome 2-3, Safari 4 и Opera 9-10 эти заголовки вызывали запрос страницы с сервера при нажатии на ссылку на страницу или указании URL-адреса. прямо в адресной строке. Это охватывает около 99% всех используемых браузеров по состоянию на январь 10 года.
В IE6 и Opera 9-10 нажатие кнопки "Назад" по-прежнему вызывало загрузку кэшированной версии. Во всех других браузерах, которые я тестировал, они получали свежую версию с сервера. До сих пор я не нашел ни одного набора заголовков, который бы заставлял эти браузеры не возвращать кэшированные версии страниц при нажатии кнопки "Назад".
Обновление: после написания этого ответа я понял, что наш веб-сервер идентифицирует себя как сервер HTTP 1.0. Заголовки, которые я перечислил, являются правильными для того, чтобы ответы от сервера HTTP 1.0 не кэшировались браузерами. Для сервера HTTP 1.1 посмотрите ответ BalusC.
Ответ 6
После небольшого исследования мы пришли к следующему списку заголовков, которые, казалось, охватывали большинство браузеров:
В ASP.NET мы добавили их, используя следующий фрагмент:
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
Найдено от: http://forums.asp.net/t/1013531.aspx
Ответ 7
Использование заголовка прагмы в ответе - это рассказ жен. RFC2616 определяет его как заголовок запроса
http://www.mnot.net/cache_docs/#PRAGMA
Ответ 8
ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Я настоятельно рекомендую прочитать ответ @BalusC. Прочитав следующий учебник по кешированию: http://www.mnot.net/cache_docs/ (я тоже рекомендую вам его прочитать), я считаю, что это правильно. Однако по историческим причинам (и потому, что я сам их протестировал), я включу свой первоначальный ответ ниже:
Я попробовал "принятый" ответ для PHP, который не работал у меня. Затем я сделал небольшое исследование, нашел небольшой вариант, протестировал его, и он сработал. Вот он:
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');
Это должно сработать. Проблема заключалась в том, что при установке одной и той же части заголовка дважды, если false
не отправляется как второй аргумент функции заголовка, функция заголовка просто перезаписывает предыдущий вызов header()
. Таким образом, при настройке Cache-Control
, например, если вы не хотите помещать все аргументы в один вызов функции header()
, он должен сделать что-то вроде этого:
header('Cache-Control: this');
header('Cache-Control: and, this', false);
См. более полную документацию здесь.
Ответ 9
Там ошибка в IE6
Содержимое с "Content-Encoding: gzip" всегда кэшируется, даже если вы используете "Cache-Control: no-cache".
http://support.microsoft.com/kb/321722
Вы можете отключить сжатие gzip для пользователей IE6 (проверьте агент пользователя для "MSIE 6")
Ответ 10
Для ядра ASP.NET создайте простой класс промежуточного слоя:
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 );
}
}
затем зарегистрируйте его с помощью Startup.cs
app.UseMiddleware<NoCacheMiddleware>();
Убедитесь, что вы добавили это где-то после
app.UseStaticFiles();
Ответ 11
Настройка измененного заголовка http на некоторую дату в 1995 году обычно делает трюк.
Вот пример:
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
Ответ 12
RFC для HTTP 1.1 говорит, что правильным способом является добавление заголовка HTTP для:
Cache-Control: no-cache
Старые браузеры могут игнорировать это, если они не соответствуют HTTP 1.1. Для них вы можете попробовать заголовок:
Pragma: no-cache
Это также должно работать для браузеров HTTP 1.1.
Ответ 13
Документация PHP для функции заголовка имеет довольно полный пример (внесенный третьей стороной):
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);
Ответ 14
Эти директивы не уменьшают риск для безопасности. Они действительно предназначены для того, чтобы заставить UA обновлять изменчивую информацию, а не держать UA в сохранении информации. См. этот похожий вопрос. По крайней мере, нет гарантии, что никакие маршрутизаторы, прокси и т.д. Не будут игнорировать также директивы кэширования.
В более позитивном плане политики, касающиеся физического доступа к компьютерам, установки программного обеспечения и т.п., поставят вас на милю впереди большинства фирм с точки зрения безопасности. Если потребители этой информации являются представителями общественности, единственное, что вы действительно можете сделать, это помочь им понять, что, как только информация попадет на их машину, эта машина их несет ответственность, а не ваша.
Ответ 15
Если вы столкнулись с проблемами с загрузкой IE6-IE8 через SSL и кеш: заголовок no-cache (и аналогичные значения) с файлами MS Office, вы можете использовать кеш: private, no-store header и возвращать файл по запросу POST. Оно работает.
Ответ 16
в моем случае я исправляю проблему в хром с этим
<form id="form1" runat="server" autocomplete="off">
где мне нужно очистить содержимое данных формы превиума, когда пользователи нажимают кнопку мыши по соображениям безопасности
Ответ 17
У меня были лучшие и самые последовательные результаты во всех браузерах, установив Pragma: no-cache
Ответ 18
Заголовки в ответе, предоставленные BalusC, не мешают Safari 5 (и, возможно, более старым версиям) отображать содержимое из кеша браузера при использовании кнопки "Назад" браузера. Способ предотвращения этого заключается в том, чтобы добавить к тегу body пустой атрибут обработчика события onunload:
<body onunload="">
Этот хак, по-видимому, разбивает кеш обратно-назад в Safari: Есть ли кросс-браузерное событие onload при нажатии кнопки "Назад" ?
Ответ 19
Принятый ответ, похоже, не работает для IIS7 +, исходя из большого количества вопросов о том, что заголовки кеша не отправляются во II7:
И так далее
Правильный ответ, в котором должны быть установлены заголовки, но не в том, как они должны быть установлены. Этот способ работает с IIS7:
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.Cache.AppendCacheExtension("no-store, must-revalidate");
Response.AppendHeader("Pragma", "no-cache");
Response.AppendHeader("Expires", "-1");
Первая строка устанавливает Cache-control
в no-cache
, а вторая строка добавляет другие атрибуты no-store, must-revalidate
Ответ 20
Кроме того, для хорошей меры убедитесь, что вы reset ExpiresDefault
в вашем файле .htaccess
, если вы используете это для включения кэширования.
ExpiresDefault "access plus 0 seconds"
Впоследствии вы можете использовать ExpiresByType
для установки определенных значений для файлов, которые вы хотите кэшировать:
ExpiresByType image/x-icon "access plus 3 month"
Это может также пригодиться, если ваши динамические файлы, например. php и т.д. кэшируются браузером, и вы не можете понять, почему. Проверьте ExpiresDefault
.
Ответ 21
В дополнение к заголовкам рассмотрим возможность обслуживания вашей страницы с помощью https. Многие браузеры не будут кэшировать https по умолчанию.
Ответ 22
//In .net MVC
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public ActionResult FareListInfo(long id)
{
}
// In .net webform
<%@ OutputCache NoStore="true" Duration="0" VaryByParam="*" %>
Ответ 23
Чтобы завершить BalusC → ANSWER
Если вы используете perl, вы можете использовать CGI для добавления заголовков HTTP.
Использование 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
))
);
}
Использование 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>
Примечание.. Когда я пытался использовать html META, браузеры игнорировали их и кэшировали страницу.
Ответ 24
Я просто хочу указать, что если кто-то хочет предотвратить кеширование ТОЛЬКО динамического контента, добавление этих дополнительных заголовков должно выполняться программно.
Я отредактировал файл конфигурации моего проекта, чтобы добавить заголовки no-cache, но также отключил кеширование статического контента, что обычно нежелательно.
Изменение заголовков ответов в коде гарантирует, что изображения и файлы стиля будут кэшироваться.
Это совершенно очевидно, но все же стоит упомянуть.
И еще одна осторожность. Будьте осторожны с использованием метода ClearHeaders класса HttpResponse. Это может дать вам несколько синяков, если вы используете его безрассудно. Мне это нравилось.
После перенаправления на событие ActionFilterAttribute последствия очистки всех заголовков теряют все данные сеанса и данные в хранилище TempData. Это безопаснее перенаправлять из действия или не очищать заголовки при переадресации.
С другой стороны, я не рекомендую использовать метод ClearHeaders. Лучше удалять заголовки отдельно. И чтобы правильно настроить заголовок Cache-Control, я использую этот код:
filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
filterContext.HttpContext.Response.Cache.AppendCacheExtension("no-store, must-revalidate");
Ответ 25
См. Эту ссылку на пример из кэширования:
http://securityevaluators.com/knowledge/case_studies/caching/
Резюме, согласно статье, только Cache-Control: no-store
работает в Chrome, Firefox и IE. IE принимает другие элементы управления, но Chrome и Firefox этого не делают. Ссылка хорошо читается с историей кэширования и документирования доказательств концепции.
Ответ 26
Мне не повезло с элементами <head><meta>
. Добавление непосредственно связанных с кешем параметров HTTP (вне HTML-документа) действительно работает для меня.
Ниже приведен пример кода в Python с использованием вызовов web.py web.header
. Я целенаправленно отредактировал свой личный неулокальный код полезности.
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()
Ответ 27
Следующий заголовок должен быть установлен в заголовке ответа:
Cache-Control: no-store, no-cache, must revalidate;
Pragma: no-cache;
For older Browsers: Set Expires = 0 or Expires = -1.