Можно ли работать с куки на фронтенде через JavaScript
Что проверяют
Знаете ли вы, какие куки JavaScript видит, а какие нет, и почему это граница безопасности. Следом почти всегда спрашивают, где хранить токен авторизации: в куке или в localStorage.
Как отвечать
Да, можно, но не со всеми куками. Классический интерфейс это document.cookie:
- чтение: геттер возвращает одну строку вида
a=1; b=2со всеми куками, доступными текущей странице, без атрибутов. Разбирать её приходится вручную, значения обычно кодируют черезencodeURIComponent; - запись: каждое присваивание ставит одну куку и не затирает остальные. Атрибуты идут через точку с запятой:
path,domain,max-ageилиexpires,secure,samesite; - удаление: та же кука с
max-age=0, причём с теми жеpathиdomain, иначе браузер создаст соседнюю, а старая останется; - HttpOnly: такую куку ставит только сервер заголовком
Set-Cookie, из JavaScript её не видно и не изменить. Поэтому сессию кладут именно туда: скрипт, внедрённый через XSS, её не прочитает.
Есть и новый асинхронный интерфейс cookieStore (cookieStore.get(), set(), событие change). Он работает только в защищённом контексте и появился в браузерах в разное время, так что перед использованием сверьтесь с таблицами поддержки.
Про атрибуты стоит сказать ещё две вещи. SameSite=None браузеры принимают только вместе с Secure, а без явного SameSite Chrome ведёт себя как при Lax. Одна кука ограничена примерно четырьмя килобайтами, и все куки домена уходят на сервер с каждым запросом, поэтому данные, которые серверу не нужны, разумнее держать в localStorage.
Где спотыкаются
Советуют ставить HttpOnly из JavaScript. Кука с этим атрибутом, выставленная через document.cookie, по спецификации не создаётся вовсе, это чисто серверная настройка.
Не могут удалить куку, потому что указывают другой path. Кука остаётся, а в коде кажется, что всё отработало.
Разбирают строку через split('=')[1] и ломаются на значении, в котором есть знак равенства, или на отсутствующей куке.