Как предотвратить кэширование определенных веб-страниц браузерами в целях безопасности во множестве браузеров, включая Internet Explorer 6 и выше, Firefox 1.5 и выше, Safari 3 и выше, Opera 9 и выше, а также Chrome? Нашему приложению требуется, чтобы определенные страницы, особенно после выхода из системы, никогда не кэшировались браузерами, чтобы предотвратить просмотр их пользователями с помощью кнопки “Назад”.
Предотвращение кэширования веб-браузеров в целях безопасности
Для предотвращения кэширования веб-браузеров в целях безопасности во множестве браузеров, включая Internet Explorer 6+, Firefox 1.5+, Safari 3+, Opera 9+ и Chrome, следует реализовать комбинацию HTTP-заголовков, которые работают последовательно во всех этих браузерах. Наиболее эффективный подход — установка заголовков Cache-Control: no-store, no-cache, must-revalidate, Pragma: no-cache и Expires: 0, а также браузерных обходных решений для Internet Explorer и Safari, которые иногда игнорируют директиву no-store при навигации назад с помощью кнопки “Назад”.
Содержание
- Поведение кэширования браузеров
- Рекомендуемые HTTP-заголовки для предотвращения кэширования
- Особенности для конкретных браузеров
- Методы реализации
- Тестирование и проверка
- Дополнительные меры безопасности
Поведение кэширования браузеров
Кэширование браузеров происходит, когда браузеры локально сохраняют копии веб-страниц для повышения производительности и снижения использования пропускной способности. Хотя это полезно для большинства контента, это становится значительным риском для безопасности для страниц, содержащих конфиденциальную информацию или состояния аутентификации, особенно после операций выхода из системы.
Разные браузеры реализуют кэширование по-разному:
- Современные браузеры (Chrome, Firefox, Edge) в целом более строго следуют спецификациям HTTP-кэширования
- Устаревшие браузеры, такие как Internet Explorer, исторически реализовывали собственные правила кэширования
- Контент по HTTPS часто кэшируется по умолчанию, если не запрещено явно
- Навигация с помощью кнопки “Назад” может обойти некоторые директивы управления кэшем в определенных браузерах
Риск для безопасности особенно актуален при использовании кнопки “Назад”, поскольку пользователи могут получить доступ к конфиденциальным страницам даже после выхода из системы, если эти страницы остаются в кэше браузера.
Рекомендуемые HTTP-заголовки для предотвращения кэширования
Для эффективного предотвращения кэширования во всех целевых браузерах следует реализовать следующие HTTP-заголовки:
Заголовок Cache-Control
Заголовок Cache-Control — это основной механизм управления кэшированием в HTTP/1.1. В целях безопасности используйте следующие директивы:
Cache-Control: no-store, no-cache, must-revalidate, max-age=0
no-store: Инструктирует браузеры не хранить никакую версию ответаno-cache: Принудительно требует повторной проверки с исходным сервером перед использованием кэшированного контентаmust-revalidate: Требует повторной проверки кэша, как только контент устареваетmax-age=0: Указывает, что контент немедленно устарел (эквивалентноExpires: 0)
Согласно Mozilla Developer Network, директива no-cache “требует от кэшей повторной проверки каждого запроса с исходным сервером”, в то время как no-store гарантирует, что “любой ответ или частичный ответ не должны храниться”.
Заголовок Pragma
Заголовок Pragma — это директива HTTP/1.0, обеспечивающая обратную совместимость:
Pragma: no-cache
Как отмечено в Microsoft Learn, “заголовок Pragma: no-cache не должен присутствовать, если заголовок Cache-Control отсутствует, поскольку при наличии заголовок Cache-Control переопределяет заголовок Pragma”.
Заголовок Expires
Заголовок Expires указывает, когда контент устаревает:
Expires: 0
Установка значения 0 представляет дату в прошлом, что заставляет немедленно устареть. Согласно ReqBin, “недопустимые даты истечения со значением 0 представляют дату в прошлом и означают, что ресурс уже устарел”.
Особенности для конкретных браузеров
Разные браузеры имеют разный уровень соответствия стандартам кэширования, что требует дополнительных соображений:
Internet Explorer 6+
Internet Explorer исторически был проблематичен с управлением кэширования:
- IE 11 игнорирует
no-storeпри навигации назад с помощью кнопки “Назад” - IE использовал политику отказа от кэширования для HTTPS как минимум с 1996 года
- Могут потребоваться дополнительные обходные решения для последовательного поведения
Согласно Gert-Jan’s Cache Control Reference, “Internet Explorer 11 игнорирует no-store” при навигации назад.
Firefox 1.5+
Firefox в целом хорошо следует стандартам кэширования:
- Поддерживает все основные директивы управления кэшем
- Рассматривает “назад” как просмотр уже просмотренного содержимого, а не повторный доступ к тому же URL
- Строго следует спецификации HTTP-кэширования, чем IE
Safari 3+
Safari имеет свои особенности:
- Safari игнорирует
no-storeв некоторых случаях - Поддерживает только
max-age=0в запросах (игнорирует другие значения) - Использует политику отказа от кэширования для контента по HTTPS (в отличие от Firefox, который перешел на эту политику в 2011 году)
Opera 9+
Поведение Opera варьируется:
- Ранние версии (v12.15) работают только с
Cache-Control: must-revalidateпо HTTPS - В целом следует стандартам, но имеет конкретные требования для определенных директив
Chrome
Поведение кэширования Chrome:
- Использует политику отказа от кэширования для HTTPS (подобно IE)
- В целом правильно следует директивам управления кэшем
- Поддерживает все основные механизмы управления кэшем
Методы реализации
Конфигурация Apache
Для серверов Apache с использованием mod_headers:
<IfModule mod_headers.c>
Header set Cache-Control "no-store, no-cache, must-revalidate, max-age=0, proxy-revalidate"
Header set Pragma "no-cache"
Header set Expires "0"
</IfModule>
Эта конфигурация, как показано на Stack Overflow, предотвратит кэширование как браузером, так и любыми промежуточными прокси-серверами.
ASP.NET Core
В ASP.NET Core используйте промежуточное ПО Response Caching:
services.AddResponseCaching();
app.UseResponseCaching();
// В вашем действии контроллера или промежуточном ПО:
HttpContext.Response.Headers["Cache-Control"] = "no-store, no-cache, must-revalidate, max-age=0";
HttpContext.Response.Headers["Pragma"] = "no-cache";
HttpContext.Response.Headers["Expires"] = "0";
Spring Security
Для приложений Spring Security настройте заголовки безопасности:
<http>
<headers>
<cache-control no-store="true" no-cache="true" must-revalidate="true" max-age="0"/>
<content-type-options nosniff="true"/>
</headers>
...
</http>
Эта конфигурация, как документировано в Spring Security, включает необходимые заголовки управления кэшем.
Конфигурация Nginx
Для серверов Nginx:
location /sensitive/ {
add_header Cache-Control "no-store, no-cache, must-revalidate, max-age=0, proxy-revalidate" always;
add_header Pragma "no-cache" always;
add_header Expires "0" always;
}
Тестирование и проверка
Чтобы убедиться, что ваши меры предотвращения кэширования работают правильно:
- Тестирование в браузерах: Протестируйте во всех целевых браузерах, используя кнопку “Назад” после выхода из системы
- Инструменты разработчика: Используйте инструменты разработчика браузера для проверки заголовков ответа
- Вкладка Сеть: Мониторьте сетевые запросы, чтобы убедиться, что свежий контент извлекается
- Анализ кэша: Очистите кэш браузера и проверьте поведение
Согласно Stack Overflow, в некоторых случаях, особенно для Internet Explorer, может потребоваться использовать “метод случайных чисел для изменения URL для базовых запросов данных”.
Дополнительные меры безопасности
В дополнение к заголовкам управления кэшем, рассмотрите эти меры безопасности:
Управление сессиями
- Реализуйте правильные таймауты сессий
- Используйте недействительность сессии на стороне сервера при выходе из системы
- Рассмотрите использование одноразовых токенов для чувствительных операций
Заголовки безопасности HTTP
Реализуйте дополнительные заголовки безопасности как часть комплексной стратегии безопасности:
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-XSS-Protection: 1; mode=block
Политика безопасности контента
Для современных браузеров реализуйте Политику безопасности контента:
Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self'
Источники
- StackHawk Docs - Incomplete or No Cache-control and Pragma HTTP Header Set
- Stack Overflow - How do we control web page caching, across all browsers?
- Mozilla Developer Network - Cache-Control header
- ReqBin - How do I disable Caching with HTTP Headers?
- Cloudflare - Origin Cache Control
- Spring Security - Security HTTP Response Headers
- RichHewlett.com - Preventing Browser Caching using HTTP Headers
- Server Fault - My browser keeps showing cached page despite sending no-cache, no-store, must-revalidate
- Microsoft Learn - Response Caching Middleware in ASP.NET Core
- Gert-Jan’s Cache Control Reference - Differences Between Web Browsers
Заключение
Предотвращение кэширования браузеров в целях безопасности требует комплексного подхода, учитывающего особенности поведения браузеров. Наиболее эффективное решение сочетает заголовки Cache-Control: no-store, no-cache, must-revalidate, max-age=0, Pragma: no-cache и Expires: 0. Однако имейте в виду, что Internet Explorer и Safari могут требовать дополнительных обходных решений, таких как рандомизация URL или управление сессиями на стороне сервера, для полного предотвращения навигации к кэшированному чувствительному контенту с помощью кнопки “Назад”.
Для оптимальной безопасности реализуйте эти заголовки как часть комплексной стратегии безопасности, которая включает правильное управление сессиями, дополнительные заголовки безопасности HTTP и тщательное тестирование во всех целевых браузерах. Всегда проверяйте, что ваша реализация работает правильно в производственных средах с реальными пользователями, поскольку поведение браузеров может варьироваться в зависимости от конкретных конфигураций и версий.