Альтернатива cookies посредством Java Script

    Поиск по хабру похожей статьи не дал, потому рискну поделится с теми кто еще не в курсе
    Многие из вас сталкивались с проблемой хранения данных на клиенте. Первым делом в голову приходит cookies но ограничение хранения данных в размере не более 4kb не всех радует, сегодня если позволите я вам расскажу как посредством Java Script хранить около 100kb на клиенте.

    В спецификации HTML5 описано несколько приемов хранения данных на клиенте не используя cookies. Рассмотрим некоторые из них либо их альтернативы по подробнее:

    The sessionStorage attribute


    Этот метод поддерживается Firefox начиная со второй версии. Это глобальный обьект, который хранится в текущей сессии документа и хранится пока документ открыт, перегружается или восстанавливается, но открытие нового окна или вкладки с тем же адресом породит новую сессию.
    Пример использования:
    sessionStorage.text = «Хабр помнит о тебе, %username%»;
    alert(«НЛО: „+sessionStorage.text);
    * This source code was highlighted with Source Code Highlighter.


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

    globalStorage


    В связи с тем что HTML5 пока еще развивается в Firefox присутствует глобальный обьект globalStorage, который позволяет хранить данные в браузере в течении долгого промежутка времени не привязываясь к сессии, что позволяет пользоваться и манипулировать сохраненными данными при открытия нового окна, вкладки, закрытия\открытия браузера. Привязка хранилища такого рода осуществляться по домену.
    Пример использования:
    // Инициализируем хранилище
    storage = globalStorage[“habrahabr.ru»];
    // Записываем значение
    storage['hello'] = 'Привет хабрахабр!';
    // Выводим значение
    alert(storage['hello']);
    // При необходимости удаляем
    delete storage['hello'];

    * This source code was highlighted with Source Code Highlighter.


    Такой подход дает нам возможность сохранить до 5 мегабайт информации на клиенте в определенном домене, и использовать наше хранилище в пределах домена и его субдоменов. Тоесть оно будет действовать как на habrahabr.ru, antyrat.habrahabr.ru и т.д.

    userData


    Но все что было описано выше действует только на Firefox (Gecko) браузеры, как же быть с IE?
    Мелкомягкие пошли другим путем, но не ограничили разработчиков в прекрасной возможности отказатса от cookies.
    Хранение данных на клиенте в ослике осуществляется работой с behavior. Спецификацию по работе с этим можно прочитать тут, а мы пока рассмотрим пример:
    <!-- Во первых нам понадобится элемент в каком мы будем хранить данные -->
    <span id=«customStorage»></span>
    <!-- Далее нам нужно инициализировать наше хранилище -->
    <script language=«javascript» type=«text/javascript»
     if(document.getElementById('customStorage')) {
      storage = document.getElementById('customStorage');
      storage.addBehavior("#default#userData");
      storage.load(«habr»);
      // Инициализация прошла и теперь мы уже можем работать с нашим хранилищем
      storage.setAttribute(«hello», «Хабрапривет!»); // Устанавливаем нашу переменную
      storage.save(«habr»); // И сохраняем ее
      // А теперь можно и вывести результат
      alert(storage.getAttribute(«hello»));
     }
    </script>
    * This source code was highlighted with Source Code Highlighter.

    Также нашему хранилищу как и в cookies можно задать время жизни, но об этом при необходимости вы сами сможете прочитать как это сделать.

    Client-side Database Storage


    Разработчики WebKit (Safari) вплотную приблизились к рекомендациям HTML5 и дали возможность создавать на клиенте базу данных.
    Перейдем сразу к примеру:
    // Открываем нашу БД
    db = openDatabase(«habrahabr», «1.0»);
    // Создаем таблицу если она еще не существует
    db.transaction(function(tx) {
     tx.executeSql(
       «CREATE TABLE IF NOT EXISTS habr (id TEXT, hello TEXT, unique(id))», // Запрос к БД
       [], // Сюда передаем при нужде переменные в наш запрос, они заменяют в нашем запросе знаки "?" по порядку
       function(tx, result) { }, // обработка в случае удачи
       function(tx, error) { alert(«НЛО: „+error.message); } // обработка в случае неудачи
     )
    });
    // Записываем значение
    db.transaction(function(tx) {
      tx.executesql(“insert into habr (id, hello) values ('1', 'Хабрапривет!')», [],
        function(result) { },
        function(tx, error) { alert(«НЛО: „+error.message); });
    });
    // Вввод результата
    db.transaction(function(tx) {
      id = 1;
       tx.executesql(“select hello from habr where id=?», [id], function(result) {
          // Выводим результат
          alert(result.rows.item(0).hello);
       }, function(tx, error) { alert(«НЛО: „+error.message); });
    });
    * This source code was highlighted with Source Code Highlighter.


    Недостатком такого подхода являеться то что с БД можна работать только в пределах домена. Поддомены не поддерживаються.
    Много информации об етом не нашол, копал вот етот пример.

    Local SharedObject


    Пользователям оперы повезло меньше всех, ни один из вышеперечисленных примеров опера не поддерживает, поэтому нужно прибегнуть к хитростям.
    Начиная с версии Flash Player 6.0.40.0 флеш поддерживает Local SharedObject, вот его то мы использовать и будем.
    Как это выглядит со стороны ActionScript:
    //Создание Local SharedObject
    theLocalSharedObject = sharedobject.getLocal(“habra»);
    //Сохранение значения
    theLocalSharedObject.data.hello = «Хабрапривет»;
    theLocalSharedObject.flush()
    //Получение значения
    hello = theLocalSharedObject.data.hello;
    * This source code was highlighted with Source Code Highlighter.

    Во флеше я сильно не силен, да и под рукой сейчас нету средств чтоб описать этот метод по подробней, поэтому расскажу саму суть, все что требуется так это создать мост взаимодействия Flash <=> JS, для взаимодействия между собой чтоб легко было передавать параметры во флеш и принимать их с его хранилища. Этот метод действителен для всего домена. Ограничения по размеру зависит от установок пользователя, по умолчанию это 100 килобайт.

    Silverlight Isolated Storage


    Если у пользователя установлен Silverlight тогда можно воспользоваться обьектом Isolated Storage спецификацию по нему можно найти тут.
    Опять таки сейчас нету возможности более подробно описывать этот метод.



    В итоге мы получили средство хранения информации на клиенте в размере от 100kb. Использовать это можно в любых целях.
    На данный момент я пишу кросс браузерный скрипт хранения данных на клиенте, какой бы посредством флеша смог бы синхронизировать хранилище в браузерах. А запись чтение без наличия флеша или когда доступ запрещен использовать встроенными функциями браузеров. Если статья покажется интересной то я выложу эту либу.

    PS: Прошу сильно не пинать за пост, так как это мой первый пост на хабре.
    PPS: А у вас тоже эта вредная привычка выделять текст перед прочтением?

    UPD: Пользователь donquijote привел ссылку на скрипт который пытается реализовать описанный механизм, единственный недостаток как по моему, это то, что при открытии другого браузера данные переносятся только ели и там и там срабатывало хранилище через flash. В своей статье я забыл учесть еще 2 очень мощьных механизма хранения данных на клиенте, это Adobe AIR и Google Gears, реализация последнего есть в приведенном скрипте, спасибо shamaniac за подсказку.

    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 43

      +2
      Хорошая статья, спасибо.
      Я слыхал о скрипте PersistJS (http://pablotron.org/?cid=1557 или тут по-русски http://www.jstoolbox.com/2008/05/22/persistjs-sessii-v-javascript-bez-cookies/) - он автоматически определяет, какой способ доступен, globalstorage либо userdata, либо что-то еще. Если вообще ничего не доступно, то флэш используется.
        +1
        Уж очень не удобно в реальности работать с этим. Все же проще будет хранить данные превыщающие 2 кб на сервере в базе, а в куках хранить их идетификатор.
          +1
          Смотря для каких целей, к примеру этим способом можно делать авто сохранение текста набранного пользователем, не обращаясь каждый раз к серверу и не тратя попусту пользовательский трафик, либо банить нарушителей. Чистку кукисов, смену айпишника, заход через прокси умеют многие, а почистить такое будет трудновато
            0
            Нарушитель может сменить браузер. Или написать в строке адреса (FireBug'е, DOM Inspector'е,...) javascript:код_удаления
              0
              Так я же говорил про кросс браузерность, тоесть флеш был бы мостом между браузерами, конешно не спорю што обойти можно все, но такой подход пока што новый, поэтому пока пользователи догадаются контролировать порядок можно
          +1
          Была статья про хранение данных в window.name, кроссбраузерно, данных тоже прилично вмещало.
            0
            Недостаток window.name в том, что если открыть ссылку в новом окне, то там сохраненные данные не доступны.
            0
            хороший способ. только далеко не всегда пользователь должени видеть подобного рода информацию.
            ИМХО проще создать сессию и хранить неограниченное количество информации на сервере.
              0
              1. Использование локального хранилища позволяет организовать обмен данным между окнами браузера (причём не важно, как эти окна были открыты и что с ними происходило)
              2. Можно сохранять данные пользователя даже в offline
            • НЛО прилетело и опубликовало эту надпись здесь
                0
                Автор, конечно, молодец. Но лично я бы не стал хранить на клиенте 100 кб данных :DDD Чем меньше, тем лучше.
                  0
                  так можно хранить и меньше =) цель статьи была донести до пользователей что cookies не единственный вид хранения данных на клиенте
                  +1
                  Не 2 кб, а 4 кб ;)
                  А еще есть возможность использовать flash storage.
                    0
                    Так я же про flash storage писал, читай подзаголовок Local SharedObject
                    +1
                    у вас опечатка storage.['hello']
                      0
                      Спасибо, поправил
                        0
                        отказатса?? :) что сделать? и вроде бы "я" на конце :)
                          0
                          Простите, вы о чем?
                            0
                            +1

                            вообще, грамматических ошибок много: "об етом не нашол"
                              0
                              Увы русскому меня никто не учил, приходится учится на своих ошибках, вы меня поправляйте если что, всегда рад замечаниям.
                        –1
                        > но ограничение хранения данных в размере не более 2kb не всех радует, сегодня если позволите я вам расскажу как посредством Java Script хранить около 100kb на клиенте.

                        Во-первых, ограничение не 2Kb, а 4Kb на куку. Во-вторых, на одном домене можно одновременно иметь до 20 кук включительно. Итого, суммарно, можно, используя механизм Cookies, оперировать 80Kb. А еще можно сжимать данные, таким образом хранить больший объем данных в этих доступных 80Kb.

                        Но в любом случае я согласен, что большие объемы данных в куках держать глупо, так как все эти данные будут отправляться на сервер при каждом реквесте.
                          0
                          насколько я помню, ограничение кук всё-таки 4 кб на домен, а не на куку
                            –1
                            И все-таки, 4 кб на куку, а не на домен. Пожалуйста, посмотрите спецификацию.
                              +2
                              For one domain name, each cookie is limited to 4,096 bytes. This total can exist as one name-value pair of 4 kilobytes (KB) or as up to 20 name-value pairs that total 4 KB.

                              http://support.microsoft.com/kb/306070

                              кукой они называют всю строчку, а не одну пару ключ-значение
                                0
                                Спасибо за ссылку, признаю свою неправоту. Спека, которой я пользовался, http://www.w3.org/Protocols/rfc2109/rfc2… (пункт 6.3) не говорит об этом прямо, и лишь дополнительная информация по приведенной Вами ссылке проясняет этот момент.
                                  0
                                  вообще ваша спека уже перекрыта следующей версией RFC 2965

                                  и обе RFC используют термин cookie для обозначения вообще всей сессионной информации
                                    0
                                    А вот насчет последнего я не уверен. Как тогда это понимать (из того же пункта 6.3, кстати это цитируется в приведенной Вами ссылке): "at least 20 cookies per unique host or domain name"? Как раз это и сбивает с толку, и вносит путаницу что они называют термином cookie - то ли одну пару ключ-значение, то ли "всю сессионную информацию"?
                                      0
                                      да, не очень удачно спека написана : (
                                        0
                                        Забавно. Только что поставил эксперимент, использовал 3 браузера - IE7, FF2 и Opera 9.27. Результаты, мягко скажем, неожиданные, и отличается от того, что в спецификации:

                                        1. IE и FF позволяют работать с 50 куками (парами ключ-значение).

                                        2. Opara позволяет работать только с 30 куками.

                                        3. Все три браузера принимают куки, суммарный размер которых больше чем 4 килобайта (как раз максимум по 4 килобайта на каждую, как в спеке), и сохраняет их на диске в полном объеме.

                                        4. Opera, когда посылает респонс, отправляет куки серверу только пока суммарный их размер не превышает 4 килобайта. Если суммарный размер кук больше, то отправляются только первые из них, суммарный размер которых в пределах 4 килобайт.

                                        5. IE и FF пытаются отправить серверу все куки что есть, игнорируя размеры. При этом сервер (в моем случае Apache 1.3) ругается на неправильный заголовок, мол, превышен размер.

                                        Итак, вывод из этой лабораторной работы. Спека - это одно, а на практике оказывается, как обычно, производители браузеров ей не очень следуют.
                                          0
                                          Опечатка: Opera, когда посылает реквест*, ...
                                            0
                                            Также, имеется в виду, что работа ведется с одним доменом.
                                              0
                                              Спасибо за обзор, поправил в статье значение на 4 килобайта, мой источник подхромал.
                                                0
                                                Да я сам сегодня про куки много нового узнал, век живи - век учись, как говорится...
                                                0
                                                ну да, все работают по-разному, разработчикам приходится полагаться на наименьший общий знаменатель
                                0
                                Если хранить данные клиента в базе данных, то в принципе можно с ними работать через Request.

                                То есть создать методы (сервер-сайд)
                                сreateCookie()
                                setCookieData($keyName,$value)
                                getCookieData()
                                removeCookie()

                                сreateCookie() - создает запись в таблице и возвращает уникальный ид который мы и будем хранить в обычной куке.
                                дальше посредством setCookieData($keyName,$value) сохраняем данные в таблице и посредством getCookieData() достаём массив данных.
                                Когда нам это всё больше не нужно, вызываем removeCookie() который стирает запись из таблицы.

                                Естественно надо продумать механизм безовастности.
                                  0
                                  В этом случае еще проблемой будет кроссбраузерность, ведь куки у каждого браузера свои
                                    0
                                    а в других случаях, что нет?
                                      +1
                                      Я просто предлагаю хранить данные на клиенте посредством браузеров, а для кросс браузерности использовать мост через Local SharedObject от флеша поддерживаемым всеми браузерами где установлен флеш, это позволит синхронизировать данные между всеми браузерами и с большей мощью использовать хранилище. Мне тут еще подсказали что помимо флеша, такой мост можно организовать посредством Google Gears либо Adobe Air, о чем я забыл упомянуть в своей статье.
                                  0
                                  Вот, теперь сайтам нужно полноценное хранилище данный на клиенте.
                                  Всё больше нужны нормальные инструменты создания интерфейсов (окон и проч.), кроссбраузерно и по стандарту.

                                  Будущее веба в изолированных веб-приложениях?
                                  И хранилище, и отрисовка окон и прочих элементов, и ещё что-нибудь?

                                  Очень мне хочется, чтоб вэб интерфейсы перешли вот в такие изолированные веб-приложения.
                                    0
                                    ну, статические сайты уже стали прошлым веком, разработчики сейчас пытаются как можно больше в страницы донести динамики и UI. И я думаю чем меньше клиент обращается к серверу, но в ту же очередь в полную мощь использует веб-приложение и динамику тем лутше.
                                    +1
                                    Раз уж упомянута возможность хранить данные в Silverlight Isolated Storage, то стоило бы вспомнить и про google gears.
                                      0
                                      Точно, и еще я видимо забыл про Adobe AIR.
                                      0
                                      возможно не совсем по теме, но в флеше существует какая то бага при работе с сессиями, в альтернативных експлореру браузерах. По непонятных мне причинам флеш по умолчанию запрашивает кукиз из папки експлорера.
                                      Тут описан пример: http://swfupload.org/forum/generaldiscus…

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

                                      Самое читаемое