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

StackOverflow https://stackoverflow.com/questions/49547

Вопрос

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

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

  • Internet Explorer 6+
  • Firefox 1.5+
  • Сафари 3+
  • Опера 9+
  • Хром

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

Это было полезно?

Решение

Введение

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

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 Веб-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-ответа и HTML-код <meta http-equiv> теги, тогда тот, который указан в заголовке HTTP-ответа, получит приоритет над HTML-метатегом.Мета-тег HTML будет использоваться только при просмотре страницы из файловой системы локального диска через file:// URL-адрес.Смотрите также Спецификация W3 HTML глава 5.2.2.Будьте осторожны с этим, когда вы не указываете их программно, потому что веб-сервер, в частности, может включать некоторые значения по умолчанию.

Как правило, вам лучше просто нет укажите мета-теги HTML, чтобы новички не путали, и полагайтесь на жесткие заголовки HTTP-ответов.Более того, именно те <meta http-equiv> теги - это недействительный в HTML5.Только тот http-equiv значения, перечисленные в Спецификация HTML5 разрешены.

Проверка фактических заголовков HTTP-ответа

Чтобы проверить то и другое, вы можете просмотреть / отладить их в HTTP traffic monitor набора инструментов разработчика webbrowser.Вы можете попасть туда, нажав клавишу F12 в Chrome / Firefox23 + / IE9 +, а затем открыв панель вкладок "Сеть" или "Net", а затем щелкнув интересующий HTTP-запрос, чтобы узнать все подробности о HTTP-запросе и ответе.Тот Самый приведенный ниже скриншот это из Chrome:

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

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

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

Другие советы

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

Прежде всего, История кнопок "Назад" - это это не тайник:

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

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

Предполагается, что Back возвращается назад во времени (к тому моменту, когда пользователь был вошел в систему).Он не переходит к ранее открытому 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.

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

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

В FireFox (версия 23.0.1) любой из них будет работать:

  1. Cache-Control: no-store

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

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

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

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

В Safari (версия 5.1.7, 7534.57.2) любой из них будет работать:

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

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

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

  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="">
    Потерпеть неудачу:Опера 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="">
    Потерпеть неудачу:Опера 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: *
    Потерпеть неудачу: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: *
    Потерпеть неудачу:Safari 5.1.7, Opera 12.15
    Успех:Chrome 28, FireFox 23, IE8

  5. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Потерпеть неудачу: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
    Успех:IE8

  7. Cache-Control: private, no-cache, must-revalidate, max-age=0, proxy-revalidate, s-maxage=0
    Expires: 0
    Pragma: no-cache
    Vary: *
    <body onunload="">
    Потерпеть неудачу: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
    Успех:IE8

  9. Cache-Control: no-store
    Потерпеть неудачу:Safari 5.1.7, Opera 12.15
    Успех:Chrome 28, FireFox 23, IE8

  10. Cache-Control: no-store
    <body onunload="">
    Потерпеть неудачу:Опера 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
    Успех:IE8

  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
    Успех:IE8

  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, Safari 5.1.7, Opera 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, IE8

  8. Cache-Control: private, no-cache, max-age=0, proxy-revalidate, s-maxage=0
    Expires: Sat, 12 Oct 1991 05:00:00 GMT
    Pragma: no-cache
    Vary: *
    Потерпеть неудачу: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, Safari 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
    Потерпеть неудачу:Опера 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="">
    Потерпеть неудачу:Опера 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="">
    Потерпеть неудачу:Опера 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
    Потерпеть неудачу:Нет
    Успех:Chrome 28, FireFox 23, IE8, Safari 5.1.7, Opera 12.15

Я нашел маршрут 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>

И вот экспресс / 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();
});

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

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

Управление кэшем:нет в магазине
Варьироваться:*

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

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

В 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, функция header просто перезапишет предыдущий header() позвони.Итак, при настройке Cache-Control, например , если кто - то не хочет помещать все аргументы в один header() вызов функции, он должен сделать что-то вроде этого:

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

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

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

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

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

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

Для 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();

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

Управление кэшем:отсутствие кэша

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

Прагма:отсутствие кэша

Предполагается, что это также должно работать для браузеров HTTP 1.1.

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

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

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

Тот Самый Документация 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 (и аналогичными значениями) с файлами MS Office, вы можете использовать cache: private, заголовок no-store и возвращать файл по запросу POST.Это работает.

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

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

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

Я добился наилучших и наиболее последовательных результатов во всех браузерах, установив Pragma:отсутствие кэша

Заголовки в ответе, предоставленном 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 Для 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="*" %>

Для завершения БалюсК -> ОТВЕТ Если вы используете 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 этого не делают.Ссылка полезна для чтения в комплекте с историей кэширования и документированием подтверждения концепции.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top