Чувствительные данные в кэше

При использовании Service Worker и библиотеки Workbox для кэширования ресурсов веб-приложений необходимо уделять особое внимание чувствительным данным. К чувствительным данным относятся токены авторизации, персональные сведения пользователей, результаты приватных API-запросов. Некорректное кэширование таких данных может привести к утечкам информации или нарушению политики безопасности приложения.

Ограничение кэширования приватных ресурсов

Workbox по умолчанию предоставляет высокоуровневые стратегии кэширования: CacheFirst, NetworkFirst, StaleWhileRevalidate, NetworkOnly и CacheOnly. Для ресурсов, содержащих чувствительные данные, следует отдавать предпочтение стратегиям, минимизирующим хранение на стороне клиента.

Пример стратегии для приватного API:

import {registerRoute} from 'workbox-routing';
import {NetworkOnly} from 'workbox-strategies';

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

В данном случае запросы к /api/private/ всегда идут к сети, исключая их попадание в кэш. Это предотвращает случайное хранение личной информации в Service Worker кэше.

Использование условного кэширования

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

Пример проверки кэша по HTTP-статусу:

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

registerRoute(
  ({url}) => url.pathname.startsWith('/api/sensitive/'),
  new CacheFirst({
    cacheName: 'sensitive-cache',
    plugins: [
      new CacheableResponsePlugin({
        statuses: [200] // только успешные ответы можно кэшировать
      })
    ]
  })
);

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

Очистка кэша и управление сроком жизни данных

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

Пример ограничения хранения:

import {ExpirationPlugin} from 'workbox-expiration';
import {StaleWhileRevalidate} from 'workbox-strategies';

registerRoute(
  ({url}) => url.pathname.startsWith('/api/sensitive/'),
  new StaleWhileRevalidate({
    cacheName: 'sensitive-cache',
    plugins: [
      new ExpirationPlugin({
        maxEntries: 50,      // максимум 50 объектов
        maxAgeSeconds: 300   // срок хранения 5 минут
      })
    ]
  })
);

Это обеспечивает автоматическое удаление устаревших данных и предотвращает накопление конфиденциальной информации.

Шифрование данных в кэше

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

import CryptoJS from 'crypto-js';

const encryptPlugin = {
  cacheWillUpdate: async ({response}) => {
    if (!response || response.status !== 200) return null;
    const clonedResponse = response.clone();
    const text = await clonedResponse.text();
    const encryptedText = CryptoJS.AES.encrypt(text, 'secret-key').toString();
    return new Response(encryptedText, {
      headers: clonedResponse.headers
    });
  }
};

registerRoute(
  ({url}) => url.pathname.startsWith('/api/sensitive/'),
  new CacheFirst({
    cacheName: 'encrypted-cache',
    plugins: [encryptPlugin]
  })
);

При последующем извлечении данных необходимо их расшифровывать перед использованием.

Ограничение кэширования по URL-параметрам

Чувствительные данные часто передаются через query-параметры (?token=...). Workbox позволяет использовать регулярные выражения или функции для фильтрации URL и исключения их из кэширования:

registerRoute(
  ({url}) => !url.searchParams.has('token'),
  new StaleWhileRevalidate()
);

Это предотвращает попадание токенов и других секретных данных в кэш.

Совмещение стратегий и плагинов

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

  • NetworkOnly для критически чувствительных запросов;
  • StaleWhileRevalidate с ограничением по времени и шифрованием для полу-конфиденциальных данных;
  • ExpirationPlugin для автоматической очистки устаревшего кэша;
  • CacheableResponsePlugin для фильтрации по статусу ответа.

Такой подход позволяет балансировать между производительностью приложения и безопасностью данных.

Практические рекомендации

  • Никогда не кэшировать токены авторизации или пароли.
  • Чувствительные данные можно кэшировать только временно и при шифровании.
  • Регулярно очищать кэш через ExpirationPlugin или при обновлении Service Worker.
  • Всегда проверять статус ответа и заголовки перед кэшированием.
  • Разделять кэш публичных и приватных ресурсов, используя разные cacheName.

Эти меры позволяют снизить риски утечки данных через Service Worker и обеспечить безопасное использование кэширования в приложениях на JavaScript с Workbox.