Постоянный кеш браузера с использованием ServiceWorker

Я разрабатываю безопасный загрузчик JavaScript. Загрузчик встроен в index.html. Цель безопасного загрузчика - загрузить только ресурсы JavaScript. Содержимое index.html в основном ограничено безопасным загрузчиком. В целях безопасности я хочу, чтобы index.html (как хранится в кеше) никогда не менялся, , даже если мой сайт взломан..

Как кэшировать index.html, если сервер не может вмешиваться в кеш? Мне интересно, может ли ServiceWorker помочь. Фактически, index.html зарегистрировал бы служебного работника для извлечения из неизменяемого кеша (сетевой запрос даже не был сделан).

Ответы

Ответ 1

Эта цель дизайна "безопасной загрузки javascript" /TOFU обычно связана с секретами криптова и браузером javascript (например, Cyph, Mega), поэтому я буду включать некоторые соответствующие рекомендации на этом пути.

Ты на опасной территории. Существует много драконов.

Вариант 1: Внесите feross/infinite-app-cache, чтобы навсегда кэшировать приложение в браузере

Здесь наименьшее количество кода, необходимое для создания веб-приложения TOFU во всех браузерах.

index.html

<html manifest="manifest.appcache">

manifest.app cache:

CACHE MANIFEST
/manifest.appcache
/index.html
/script-loader.js

И убедитесь, что вы обслуживаете манифест с типом содержимого "text/cache-manifest".

Примечание. Этот стандарт устарел, однако потребуется несколько лет, прежде чем браузер отключит эту функцию.

Проблема. Если злоумышленник (который уже взломал ваш сервер) может обмануть ваших пользователей при посещении URL-адреса, не входящего в кеш приложения, он может обслуживать произвольный код для извлечения/использования секретов браузера и т.д.

Решение: вход пользователя не может быть перехвачен вредоносной страницей в том же домене (если вы не делаете что-то действительно глупо), поэтому шифруйте все секреты браузера с помощью пароля, предоставленного пользователем, и dchest/scrypt- Асинхры-JS.

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

Вариант 2: Расширьте вышеуказанное решение с помощью самоубийства HPKP и сотрудника службы поддержки

Внедрите самоубийство HPKP, чтобы надолго "испечь" приложение в браузере, отключив подключение пользователя к серверу.

Если (и только если) вы внедрили самоубийство HPKP, сервис-работники теперь безопасны в использовании, поскольку принудительный максимальный возраст 24 часа не действует, если браузер не может повторно загрузить обслуживающего работника.

index.html или script -loader.js:

if ('serviceWorker' in navigator) {
  window.addEventListener('load', function() {
    navigator.serviceWorker.register('/service-worker.js').catch(function (error) {
      console.error(error);
    });
  });
}

сервис-worker.js:

var files = [ 
  '/',
  'index.html',
  'script-loader.js'
].map(file => new Request(file))

self.addEventListener('install', () => {  
  caches.open('cache')
    .then(cache => {
      files.map(file => {
        fetch(file)
          .then(response => cache.put(file, response))
          .catch(err => console.error(err))
      })
    })
    .catch(err => console.error(err))
})

self.addEventListener('fetch', (e) => {
  var url = e.request.url.split('#')[0]

  if (!files.filter(file => file.url === url).length) {
    return e.respondWith(new Response('Not Found', { status: 404 }))
  }

  return e.respondWith(
    caches.match(e.request).then(cachedResponse => {
      if (cachedResponse) return cachedResponse

      return Promise.all([
        caches.open('cache'),
        fetch(e.request.clone())
      ]).then((results) => {
        var cache = results[0]
        var response = results[1]

        cache.put(e.request, response.clone())

        return response
      })
    })
  )
})

Важное примечание. Без самоубийства HPKP использование сервисного работ МЕНЬЕ безопасно, чем бесконечный кеш приложений, поскольку рабочий сервис имеет максимальный возраст 24 часа, даже если ваши директивы кэша сервера устанавливают более высокий возраст. Использование сервисных работников также полностью отключит кеш приложений. Это пустая трата времени, пытаясь добиться этого с работниками сферы услуг, если вы не реализовали самоубийство HPKP.

Обсуждение

  • Самоубийство HPKP потеряло гарантию постоянства в Chrome, поскольку они недавно внедрили максимальный возраст 60 дней (см. вопрос № 523654 для обсуждения).
  • Я настоятельно рекомендую использовать TweetNaCl.js для всех криптоваторов браузера: он требует усилий для неправильного использования и, если вы не шифруете большие файлы, разница в производительности с WebCrypto невелика.

Ответ 2

в хром вы можете использовать API файловой системы

http://www.noupe.com/design/html5-filesystem-api-create-files-store-locally-using-javascript-webkit.html, это позволяет вам сохранять и читать файлы из файловой системы с песочницей, хотя браузер.

Что касается другой поддержки, она еще не подтверждена как дополнение к спецификации спецификации HTML5. поэтому он доступен только в хроме.

Вы также можете использовать систему IndexDB, которая поддерживается во всех современных браузерах.

вы можете использовать обе эти службы внутри Service Worker для управления загрузкой и управлением содержимым, однако я должен задать вопрос, почему вы хотите, чтобы вы не позволяли себе обновлять свой index.html

Ответ 3

Вы также можете использовать Cache API, который может сохранять ответы ваших запросов (все виды запросов - html-страницы, запросы api, изображений). Но обратите внимание, что в настоящее время он поддерживается только в Chrome и Firefox.

На этой странице также показан пример использования fetch