Как управлять кэшированием веб-страниц во всех браузерах?

наши исследования показали нам, что не все браузеры уважают директивы кэша http единообразно.

по соображениям безопасности мы не хотим, чтобы определенные страницы в нашем приложении кэшировались,никогда, веб-браузером. Это должно работать по крайней мере для следующих браузеров:

  • Internet Explorer 6+
  • Firefox 1.5+
  • сафари 3+
  • Opera 9+
  • Chrome

наши требование пришло из теста безопасности. После выхода с нашего сайта вы можете нажать кнопку "назад" и просмотреть кэшированные страницы.

26 ответов


введение

правильный минимальный набор заголовков, который работает во всех упомянутых клиентов (и прокси):

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

на Cache-Control соответствует спецификации HTTP 1.1 для клиентов и прокси (и неявно требуется некоторыми клиентами рядом с Expires). The Pragma соответствует спецификации HTTP 1.0 для доисторических клиентов. The 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 не имеют значения, если вышеуказанные параметры. Этот Last-Modified заголовок, включенный в большинство других ответов, здесь только интересны, если вы на самом деле хочу!--67--> для кэширования запроса, поэтому вам не нужно указывать его вообще.

Как установить?

использование 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 или узла.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:

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.

Использование 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')
    )
)

Использование 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.

Использование Apache :

<IfModule mod_headers.c>
    Header set Cache-Control "no-cache, no-store, must-revalidate"
    Header set Pragma "no-cache"
    Header set Expires 0
</IfModule>

использование 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 и 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 traffic monitor набора инструментов разработчика webbrowser. Вы можете попасть туда, нажав F12 в Chrome/Firefox23+ / IE9+, а затем открыв вкладку "Сеть" или "сеть", а затем нажав на интересующий HTTP-запрос, чтобы раскрыть все подробности о HTTP-запросе и ответе. The ниже экрана из Chrome:

Chrome developer toolset HTTP traffic monitor showing HTTP response headers on stackoverflow.com

я тоже хочу установить эти заголовки при загрузке файлов

прежде всего, этот вопрос и ответ нацелены на "веб-страницы "(HTML-страницы), а не" загрузки файлов " (PDF, zip, Excel и т. д.). Вам лучше кэшировать их и использовать идентификатор версии файла где-то в пути URI или querystring, чтобы принудительно перезагрузить измененный файл. При применении этих заголовков без кэша при загрузке файлов в любом случае остерегайтесь ошибки IE7/8 при обслуживании загрузки файлов по HTTPS вместо HTTP. Подробнее см. IE не может загрузить foo.в JSF. IE не смог открыть это сайт. Узел недоступен или не найден.


(Эй, все: пожалуйста, не просто бездумно копировать и вставлять все заголовки, которые вы можете найти)

прежде всего, история кнопки Назад не кэш:

модель свежести (раздел 4.2) не обязательно применяется к механизмам истории. То есть механизм истории может отображать предыдущее представление, даже если оно истекло.

в старой спецификации HTTP формулировка была еще сильнее, явно указание браузерам игнорировать директивы кэша для истории кнопок "Назад".

Back должен вернуться во времени (к тому времени, когда пользователь был logged in). Он не переходит к ранее открытому URL-адресу.

однако на практике кэш может влиять на кнопку "Назад" в очень конкретных обстоятельствах:

  • страница должны в течение HTTPS, в противном случае этот кэш-перебор не будет надежный. Кроме того, если вы не используете HTTPS, ваша страница уязвима для кражи входа во многих других способах.
  • вы должны отправить Cache-Control: no-store, must-revalidate (некоторые браузеры наблюдать no-store и в must-revalidate)

вы никогда надо:

  • <meta> с заголовками кэша - он вообще не работает. Абсолютно бесполезный.
  • post-check/pre-check - это директива IE-only, которая применяется только к cachable ресурсы.
  • отправка одного и того же заголовка дважды или в дюжине частей. Некоторые фрагменты PHP фактически заменяют предыдущие заголовки, в результате чего отправляется только последний.

если вы хотите, вы можете добавить:

  • no-cache или max-age=0, что сделает ресурс (URL) "устаревшим" и потребует от браузеров проверки с сервером, если есть более новая версия (no-store уже предполагает это еще сильнее).
  • Expires С датой в прошлом Клиенты HTTP/1.0 (хотя реальные HTTP/1.0-в наши дни полностью отсутствуют только клиенты).

бонус: новый HTTP кэширование RFC.


как заявил porneL, вы хотите не деактивировать кэш, а деактивировать буфер истории. Различные браузеры имеют свои собственные тонкие способы отключения буфера истории.

в Chrome (v28.0.1500.95 м) мы можем сделать это только Cache-Control: no-store.

в FireFox (v23.0.1) любой из них будет работать:

  1. Cache-Control: no-store

  2. Cache-Control: no-cache (https только)

  3. Pragma: no-cache (только https)

  4. Vary: * (только https)

в опере (версии 12.15) мы можем только сделать это Cache-Control: must-revalidate (только https).

в Safari (v5.1.7, 7534.57.2) любой из них будет работать:

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

  2. Cache-Control: no-store (только https)

In IE8 (v8.0.6001.18702 IC) любой из них будет работать:

  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 (только https)

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

  1. Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Fail: Opera 12.15
    успех: Chrome 28, FireFox 23, IE8, Safari 5.1.7

  2. Cache-Control: private, no-cache, no-store, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Fail: Opera 12.15
    Успех: 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
    успех: 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
    Успех: Chrome 28, FireFox 23, ИЕ8

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

  6. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Сбой: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    успех: ИЕ8

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

  8. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Сбой: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    успех: ИЕ8

  9. Cache-Control: no-store
    Fail: Safari 5.1.7, Opera 12.15
    успех: Chrome 28, FireFox 23, IE8

  10. Cache-Control: no-store
    <body onunload="">
    Fail: Opera 12.15
    успех: Chrome 28, FireFox 23, IE8, Safari 5.1.7

  11. Cache-Control: no-cache
    Сбой: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    успех: ИЕ8

  12. Vary: *
    сбой: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    успех: ничего

  13. Pragma: no-cache
    сбой: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15
    успех: ничего

  14. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Сбой: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    успех: IE8

  15. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Сбой: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    успех: IE8

  16. Cache-Control: must-revalidate, max-age=0
    Сбой: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    успех: ИЕ8

  17. Cache-Control: must-revalidate
    Expires: 0
    Сбой: Chrome 28, FireFox 23, Safari 5.1.7, Opera 12.15
    успех: IE8

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

  19. 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
    успех: ничего

HTTPS и:

  1. 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
    успех: ничего

  2. 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, Сафари 5.1.7, Опера 12.15
    успех: ничего

  3. Vary: *
    Сбой: Chrome 28, Safari 5.1.7, Opera 12.15
    успех: FireFox 23, IE8

  4. Pragma: no-cache
    Сбой: Chrome 28, Safari 5.1.7, Opera 12.15
    успех: FireFox 23, IE8

  5. Cache-Control: no-cache
    Сбой: Chrome 28, Safari 5.1.7, Opera 12.15
    успех: FireFox 23, IE8

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

  7. 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, ИЕ8

  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: *
    Сбой: Chrome 28, Safari 5.1.7, Opera 12.15
    успех: FireFox 23, IE8

  9. Cache-Control: must-revalidate
    сбой: Chrome 28, FireFox 23, IE8, Safari 5.1.7
    Успех: Опера 12.15

  10. Cache-Control: private, must-revalidate, proxy-revalidate, s-maxage=0
    <body onunload="">
    сбой: Chrome 28, FireFox 23, IE8, Сафари 5.1.7
    Успех: Опера 12.15

  11. Cache-Control: must-revalidate, max-age=0
    Сбой: Chrome 28, FireFox 23, Safari 5.1.7
    успех: IE8, Opera 12.15

  12. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Сбой: Chrome 28, Safari 5.1.7
    успех: FireFox 23, IE8, Opera 12.15

  13. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Сбой: Chrome 28, Safari 5.1.7
    успех: FireFox 23, IE8, Opera 12.15

  14. Cache-Control: no-store
    Fail: Opera 12.15
    успех: Chrome 28, FireFox 23, IE8, Safari 5.1.7

  15. Cache-Control: private, no-cache, no-store, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Fail: Opera 12.15
    успех: Chrome 28, FireFox 23, IE8, Safari 5.1.7

  16. Cache-Control: private, no-cache, no-store, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Fail: Opera 12.15
    успех: 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: *
    Сбой: Chrome 28, Safari 5.1.7, Opera 12.15
    успех: FireFox 23, IE8

  18. Cache-Control: must-revalidate
    Expires: 0
    Сбой: Chrome 28, FireFox 23, Safari 5.1.7,
    успех: IE8, Opera 12.15

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

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

  21. Cache-Control: private, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    <body onunload="">
    Сбой: Chrome 28, FireFox 23, Safari 5.1.7,
    успех: IE8, Opera 12.15

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

  23. Cache-Control: no-store, must-revalidate
    Fail: нет
    успех: Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15


Я нашел в интернете.config route полезен (пытался добавить его в ответ, но, похоже, не был принят, поэтому разместите здесь)

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

и вот экспресс / узел.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();
});

Я обнаружил, что все ответы на этой странице все еще имели проблемы. В частности, я заметил, что ни один из них не остановит IE8 от использования кэшированной версии страницы при доступе к ней, нажав кнопку "Назад".

после долгих исследований и тестирования я обнаружил, что мне действительно нужны только два заголовка:

Cache-Control: no-store
Vary:*

для объяснения заголовка 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 ответ.


после небольшого исследования, мы придумали следующий список заголовков, которые, казалось, покрывали большинство браузеров:

In 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


использование заголовка pragma в ответе-это история жен. RFC2616 определяет его только как заголовок запроса

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


отказ от ответственности: я настоятельно рекомендую прочитать ответ @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);

посмотреть более полную документацию здесь.


в IE6 есть ошибка

содержимое с "Content-Encoding: gzip" всегда кэшируется, даже если вы используете "Cache-Control: no-cache".

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

вы можете отключить сжатие gzip для пользователей IE6 (проверьте агент пользователя для "MSIE 6")


RFC для HTTP 1.1 говорит, что правильный метод-добавить HTTP-заголовок для:

кэш-управления: нет-кэш

старые браузеры могут игнорировать это, если они не соответствуют HTTP 1.1. Для тех, кто вы можете попробовать заголовок:

Pragma: no-cache

Это также должно работать для браузеров HTTP 1.1.


эти директивы не уменьшают никакой риск для безопасности. Они действительно предназначены для того, чтобы заставить UA обновлять изменчивую информацию, а не удерживать UA от сохранения информации. См.этот же вопрос. По крайней мере, нет никакой гарантии, что все маршрутизаторы, прокси и т. д. также не будет игнорировать директивы кэширования.

на более положительной ноте, политики в отношении физического доступа к компьютерам, установки программного обеспечения и тому подобное поставят вам мили опережает большинство фирм в плане безопасности. Если потребители этой информации являются представителями общественности, единственное, что вы действительно можете сделать, это помочь им понять, что как только информация попадает на их машину, эта машина их ответственность, не твоя.


на документация 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);

Если вы столкнулись с проблемами загрузки с IE6-IE8 через SSL и cache:no-cache header (и аналогичные значения) с файлами MS Office,вы можете использовать cache: private, no-store header и return file по запросу POST. Это работает.


в моем случае я исправляю проблему в chrome с помощью этого

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

где мне нужно очистить содержимое данных формы previus, когда пользователи нажимают кнопку назад по соображениям безопасности


для ASP.NET Core, создайте простой промежуточный класс:

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

установка измененного заголовка 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

У меня были лучшие и наиболее последовательные результаты во всех браузерах, установив Pragma: no-cache


заголовки в ответе, предоставленном BalusC, не препятствуют Safari 5 (и, возможно, более старым версиям) отображать содержимое из кэша браузера при использовании кнопки "Назад" браузера. Способ предотвратить это-добавить пустой атрибут обработчика событий onunload в тег body:

<body onunload=""> 

этот хак, по-видимому, ломает кэш назад-вперед в Safari:есть ли кросс-браузерное событие onload при нажатии кнопки "Назад"?


принятый ответ, похоже, не работает для 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 to no-cache, а вторая строка добавляет другие атрибуты no-store, must-revalidate


кроме того, просто для хорошей меры, убедитесь, что вы сбросили ExpiresDefault в своем .htaccess файл, если вы используете это для включения кэширования.

ExpiresDefault "access plus 0 seconds"

после этого вы можете использовать ExpiresByType установить конкретные значения для файлов, которые вы хотите кэшировать:

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

это также может пригодиться, если ваши динамические файлы, например php и т. д. кэшируются браузером, и вы не можете понять, почему. Проверка ExpiresDefault.


в дополнение к заголовкам рассмотрите возможность обслуживания вашей страницы через https. Многие браузеры не будут кэшировать https по умолчанию.


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

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

завершить BalusC ->ответ Если вы используете 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, браузеры игнорировали их и кэшировали страницу.


Я просто хочу отметить, что если кто-то хочет предотвратить кэширование только динамического контента, добавление этих дополнительных заголовков должно быть сделано программно.

я отредактировал файл конфигурации моего проекта, чтобы добавить заголовки без кэша, но это также отключило кэширование статического содержимого, что обычно нежелательно. Изменение заголовков ответов в коде гарантирует кэширование изображений и файлов стилей.

Это совершенно очевидно, но все же стоит упоминание.

и еще одно предостережение. Будьте осторожны, используя метод ClearHeaders из класса HttpResponse. Это может дать вам некоторые синяки, если вы используете его напропалую. Как будто это дало мне.

после перенаправления на событии ActionFilterAttribute последствия очистки всех заголовков теряют все данные сеанса и данные в хранилище TempData. Безопаснее перенаправлять из действия или не очищать заголовки при перенаправлении.

на секунду подумал, что я обескураживаю всех для использования метода ClearHeaders. Заголовки лучше удалять отдельно. И чтобы правильно установить заголовок Cache-Control, я использую этот код:

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

мне не повезло с <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()


см. эту ссылку на тематическое исследование по кэшированию:

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

резюме, согласно статье, только Cache-Control: no-store работает на Chrome, Firefox и IE. IE принимает другие элементы управления, но Chrome и Firefox-нет. Ссылка хорошо читается в комплекте с историей кэширования и документального подтверждения концепции.