Сохранение данных на стороне клиента

API браузеров для хранения данных пользователя локально (на стороне клиента).

Доступ к данным на стороне клиента ограничен - данные предоставляются только для ресурсов с общего домена. Т.е. страницы одного домена могут использовать данные хранилища, связанные с этим доменом. А страницам других доменов будет отказано в доступе.

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

Два основных типа хранения данных: Web Storage (sessionStorage и localStorage ) и Cookies.

Web Storage

API Web Storage - это обычный конструктор объекта с названием Storage. Этот конструктор генерирует объект при создании страницы. Это всегда новый объект. И это новый объект для каждой новой страницы, даже если пытаться открыть одну и ту же ссылку. Свойства и ключи Storage всегда являются string. Разница между localStorage и sessionStorage заключается лишь в сроке хранения и области видимости.

Максимальный размер Web Storage

Посмотреть максимальный размер Web Storage для версий старых браузеров можно по ссылке. В общем случае можно рассчитывать на 2Мб, а для современных браузеров и на 10Мб.

Методы Web Storage

Пример использования


Задать 
    ключ и ­зна­че­ние:                   
localStorage.setItem(
    'myKey', ключ
    'myValue'значение
);    
­По­лу­чить­ 
    со­хра­нен­ное ­зна­че­ние:                 
const myString = localStorage
    .getItem('myKey');
 'myValue'
­По­лу­чить­ 
        со­хра­нен­ный ключ:                 
const Key = localStorage
    .key(0);
'myKey'
    
                

Доступность данных

Доступность данных определяется

Пример недоступности данных для сайта https://goit.ua (документы с разным происхождением)

 
http://goit.ua 
http vs https

http://fe.goit.ua 
fe.goit vs goit 

http://goit.ua:8000 
8000 vs 8080
                

Проверить Web Storage на странице с общим происхождением

Событие storage

Если в одном из окон с общим происхождением произвести изменение Web Storage, то во всех окнах (кроме текущего) будет сгенерировано событие storage. Это событие делает доступным изменения в Web Storage всем открытым окнам с общим происхождением.

Список свойств события storage

Для проверки события откройте в другой вкладке соседнее окно test.html и сгенерируйте событие в текущем окне. Ключи и значения этого события будут отображены на странице test.html

sessionStorage

Свойство sessionStorage хранит данные в течение сеанса (до закрытия браузера) -

Если браузер восстановит закрытую вкладку, то восстановит и sessionStorage (не 100%)

В каждом окне браузера - свой sessionStorage, даже если это одна и та же страница!

localStorage

Свойство localStorage не имеет ограничений по времени хранения и может быть удалено только с помощью JavaScript

Преобразования в строку. Преобразование из строки.

тип в строку из строки
Date let str = (new Date()).toUTCString() let date = Date.parse(str)
Object let str = JSON.stringify(obj) let oj = JSON.parse(str)

Cookie

Cookie - это строки пар ключ-значения и их атрибуты, сохраняемых браузером. Размер одного Cookie не может быть более 4Kb.

Важно учесть, что символ в JavaScript занимает 2 байта из-за UTF16, а в Cookie помещает символа в 1 байт из-за UTF8. При этом кириллический символ отображается несколькими ASCII символами: "Ї" преобразуется в "%D0%87"

На низшем уровне реализованы как расширение протокола HTTP

Данные в cookies автоматически передаются между браузером и веб-сервером

Поддерживают политику доступности данных (общее происхождение)

Разрешение на использование Cookie


navigator.cookieEnabled

Т.к. способ не стандартизирован, то стоит подстраховаться:


navigator.cookieEnabled 
|| document.cookie.length > 0

CRUD для Cookie или encodeURIComponent и decodeURIComponent

R (read)

Чтение всех Cookie текущего документа: document.cookie

Получим строку вида "key=value; key1=value1;"

Декодирование Строка по протоколу HTTP должна быть в формате UTF8, а в JavaScript строка в формате UTF16. Проблема заметна когда символы выходят за ASCII набор:

 
исходная строка                  
let uri = "видео/video.flv"  

кодируем для web                  
let webUri = 
  encodeURIComponent(uri);
%D0%B2%D0%B8%D0%B4%D0
    %B5%D0%BE%2Fvideo.flv       

декодируем для JS                  
let dec = 
  decodeURIComponent(webUri);
видео/video.flv   
                

Для работы с ключами и значениями придется использовать методы работы со строками, например .split()

С (create)

document.cookie = "newKey=newValue;" можно запись только одну пару с атрибутами

Сложность в том, что надо перевести текст в формат UTF8 и исключить ряд символов запрещенных протоколом HTTP ;, : document.cookie = ­encodeURIComponent( "newKey=newValue;" )

U (update) - требуются ­decodeURIComponent, ­encodeURIComponent и методы работы со строками, например .replace(). Для замены потребуется указать ключ, новое значение и все объявленные для этой пары атрибуты.

D (delete) - требуются ­­decodeURIComponent, encodeURIComponent и методы работы со строками для замены атрибута max-age на "max-age:0". Для удаления потребуется указать ключ, новое значение и все объявленные для этой пары атрибуты.

Учитывая все эти сложности реализован фреймворк для работы с Cookie поддерживающий методы

Атрибуты Cookie

Атрибуты должны идти после пары key=value и разделяться точкой с запятой.

Срок хранения

Записанный Cookie в виде пары ключ=значение является сессионным, т.е. время жизни составит время до закрытия окна браузера.

max-age атрибут, добавленный после пары ключ=значение укажет срок хранения в секундах. Пример записи:

 
let days =  
    14*24*60*60 + ";";
14 дней в секундах

let pairs = 
    ­encodeURIComponent(
        "key:value;"
    )

­document.cookie ­=
 pairs + "max-age=" + days;

                

Область видимости

Аналогично max-age можно дописать атрибуты, определяющие область видимости: path, domain и secure

Для изменения значения Cookie потребуется указать все атрибуты (option) и ключ.

Для удаления значения Cookie потребуется указать все атрибуты (option) и ключ. Но атрибуту max-age следует присвоить значение 0.

path указывает путь к документу. Если path не указан, то это путь к текущему документу.

Путь должен быть абсолютным /pages

domain указывает имя хоста. Если domain не указан, то это имя текущего хоста без sub-domen. Если домен указан, все sub-domen всегда включаются

Пример goit.ua или fe.goit.ua

secure Cookie могут передаваться только через безопасный протокол, такой как https

Безопасность использования Cookie

Описание возможности атак на Cookie вашего сайта содержит перечень основных атак.