Кэширование ответов с авторизацией

Кэширование ответов, требующих авторизации, представляет собой одну из сложных задач при использовании Service Worker и Workbox, поскольку стандартные стратегии кэширования ориентированы на публичные ресурсы. Для обработки защищённых ресурсов важно учитывать особенности заголовков Authorization, управление сроками жизни кэша и безопасность данных.

Основные принципы

  1. Изоляция кэша авторизованных данных Кэширование запросов с токеном авторизации требует отдельного хранилища. Workbox позволяет создавать разные кэш-объекты с уникальными именами, что предотвращает смешение защищённых и публичных данных.

  2. Проверка токена Каждый запрос к защищённому ресурсу должен включать актуальный токен (Bearer). Workbox позволяет изменять запрос перед его обработкой с помощью хуков requestWillFetch и fetchDidSucceed, что удобно для динамической вставки токена.

  3. Политика безопасности Кэш авторизованных ресурсов должен использовать Cache-Control: private и быть ограничен по сроку жизни. Workbox поддерживает параметры maxAgeSeconds и maxEntries для управления размером и временем хранения.

Настройка кэширования авторизованных запросов

Пример стратегии кэширования с авторизацией:

import {registerRoute} from 'workbox-routing';
import {CacheFirst} from 'workbox-strategies';
import {ExpirationPlugin} from 'workbox-expiration';

registerRoute(
  ({url, request}) => url.pathname.startsWith('/api/private') && request.headers.has('Authorization'),
  new CacheFirst({
    cacheName: 'private-api-cache',
    plugins: [
      new ExpirationPlugin({
        maxEntries: 50,
        maxAgeSeconds: 300 // кэш живет 5 минут
      })
    ],
    matchOptions: {
      ignoreSearch: false
    }
  })
);

Объяснение ключевых элементов:

  • CacheFirst выбирается для уменьшения нагрузки на сервер, отдавая данные из кэша, если они существуют и актуальны.
  • ExpirationPlugin гарантирует автоматическую очистку устаревших записей.
  • matchOptions.ignoreSearch: false обеспечивает корректное различие URL с разными query-параметрами, что критично для API с параметрами запроса.

Динамическая подмена токена

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

import {strategies} from 'workbox-strategies';

const authStrategy = new strategies.NetworkFirst({
  cacheName: 'auth-api-cache',
  plugins: [
    {
      requestWillFetch: async ({request}) => {
        const token = await getToken(); // функция получения актуального токена
        const newHeaders = new Headers(request.headers);
        newHeaders.set('Authorization', `Bearer ${token}`);
        return new Request(request, {headers: newHeaders});
      }
    }
  ]
});

registerRoute(
  ({url}) => url.pathname.startsWith('/api/private'),
  authStrategy
);

Особенности:

  • NetworkFirst позволяет отдавать свежие данные, при этом кэш используется как fallback при оффлайн-режиме.
  • Хук requestWillFetch позволяет динамически вставлять токен перед отправкой запроса.

Управление временем жизни и очисткой кэша

Для авторизованных данных особенно важно контролировать срок хранения:

import {CacheableResponsePlugin} from 'workbox-cacheable-response';

new CacheFirst({
  cacheName: 'private-api-cache',
  plugins: [
    new CacheableResponsePlugin({
      statuses: [200] // кэшируем только успешные ответы
    }),
    new ExpirationPlugin({
      maxAgeSeconds: 300,
      maxEntries: 50
    })
  ]
});
  • CacheableResponsePlugin предотвращает сохранение в кэш ошибок и редиректов.
  • Ограничение количества записей защищает от переполнения памяти в браузере.

Рекомендации по безопасности

  • Никогда не сохранять в кэш пароли или чувствительные данные в открытом виде.
  • Кэш авторизованных запросов следует использовать только внутри защищённого контекста (HTTPS, правильные политики CORS).
  • При смене токена старые кэши должны удаляться или инвалидироваться, чтобы избежать использования устаревших данных.

Логика обновления и инвалидации кэша

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

self.addEventListener('message', (event) => {
  if (event.data && event.data.type === 'CLEAR_AUTH_CACHE') {
    caches.delete('private-api-cache');
  }
});
  • Через postMessage можно уведомлять Service Worker о необходимости очистки кэша при выходе пользователя из системы или смене токена.

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