HTTP cookie
07.10.2018
Теги: Cookie • HTTP • HTTPS • JavaScript • localStorage • PHP • php.ini • sessionStorage • Web-разработка
HTTP cookie — это небольшой фрагмент данных, отправляемый сервером браузеру пользователя, который тот должен сохранить и отсылать обратно с каждым новым запросом этому серверу. Это, в частности, позволяет узнать, с одного ли браузера пришли оба запроса (например, для аутентификации пользователя). Они запоминают информацию о состоянии для протокола HTTP, который сам по себе этого делать не умеет.
Cookie используются, главным образом, для:
- Управления сеансом (логины, корзины для интернет-магазинов)
- Персонализации (пользовательские предпочтения)
- Мониторинга (отслеживания поведения пользователя)
Кроме того, до недавнего времени было принято использовать cookie в качестве хранилища информации на стороне пользователя. Но из-за того, что cookie пересылаются с каждым запросом, они могут сильно снижать производительность (особенно в мобильных устройствах). Теперь качестве хранилищ данных на стороне пользователя вместо них можно использовать localStorage, sessionStorage и IndexedDB.
Создание cookie
Получив HTTP-запрос, вместе с ответом сервер может отправить заголовок Set-Cookie
. Cookie запоминаются браузером и посылаются серверу с каждым новым запросом. Можно задать срок действия cookie, то есть срок его жизни, после которого cookie не будет отправляться. Также можно указать ограничения на путь и домен, то есть указать, где cookie будет действовать — по какому пути и на каком домене. Например, cookie будут действительны для пути www.server.com/private
или для домена private.server.com
.
Заголовки Set-Cookie и Cookie
Заголовок Set-Cookie
используется для отправки cookie с сервера на клиентское приложение (браузер). Этот заголовок с сервера дает клиенту указание сохранить cookie.
Set-Cookie: <имя-cookie>=<значение-cookie>
HTTP/1.1 200 OK Date: Sun, 07 Oct 2018 13:31:17 GMT Server: Apache/2.4.34 (Win64) mod_fcgid/2.3.9 X-Powered-By: PHP/7.1.10 Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate Pragma: no-cache Set-Cookie: PHPSESSID=m2iut9i59p73ld1c5q9j49c6t0; path=/ Set-Cookie: visitor=0d3749f09d222bea3b8f163937eb9bf1; Max-Age=31536000; path=/ Set-Cookie: lastvisit=1538919655; path=/ Vary: Accept-Encoding Content-Encoding: gzip Keep-Alive: timeout=5, max=100 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: text/html; charset=utf-8 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru" lang="ru"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> ..........
Теперь, с каждым новым запросом к серверу, при помощи заголовка Cookie
браузер будет возвращать серверу все сохраненные ранее cookies:
GET /catalog HTTP/1.1
Host: www.server.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:62.0) Gecko/20100101 Firefox/62.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://www.server.com/
Cookie: PHPSESSID=m2iut9i59p73ld1c5q9j49c6t0; visitor=0d3749f09d222bea3b8f163937eb9bf1; lastvisit=1538919655
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Сессионные, постоянные и безопасные cookie
Сессионные cookie, установка которых выглядит так:
Set-Cookie: lastvisit=1538919655
удаляются при закрытии окна браузера, то есть существуют только на протяжении текущего сеанса, поскольку атрибуты Expires
или Max-Age
для них не задаются.
Постоянные cookie удаляются не с закрытием клиента, а при наступлении определенной даты (атрибут Expires
) или после определенного интервала времени (атрибут Max-Age
):
Set-Cookie: visitor=0d3749f09d222bea3b8f163937eb9bf1; Max-Age=31536000
Set-Cookie: visitor=0d3749f09d222bea3b8f163937eb9bf1; expires=Mon, 07-Oct-2019 13:44:02 GMT
Безопасные cookie отсылаются на сервер только если запрос выполняется по протоколу SSL и HTTPS. Начиная с Chrome 52 и Firefox 52, незащищенные сайты (HTTP) не могут создавать куки с флагом secure
.
Set-Cookie: PHPSESSID=m2iut9i59p73ld1c5q9j49c6t0; Secure
HttpOnly cookie не доступны из JavaScript через свойство document.cookie
и через XMLHttpRequest
, что помогает избежать межсайтового скриптинга (XSS). Рекомендуется устанавливать этот флаг для тех cookie, к которым не требуется обращаться через JavaScript. В частности, если куки используются только для поддержки сеанса, то в JavaScript они не нужны, так что в этом случае следует устанавливать флаг HttpOnly
:
Set-Cookie: PHPSESSID=m2iut9i59p73ld1c5q9j49c6t0; Secure; HttpOnly
Область видимости cookie
Директивы domain
и path
определяют область видимости куки, то есть те URL, к которым куки могут отсылаться.
- Атрибут
domain
указывает хосты, к которым отсылаться куки. Если он не задан, то по умолчанию берется доменная часть документа (но без поддоменов). Если домен указан явно, то поддомены всегда включены. Например, если заданоdomain=server.com
, то куки включены и в поддоменах, например, вblog.server.com
. - Атрибут
path
указывает URL, который должен быть в запрашиваемом ресурсе на момент отправки заголовка. Символ «/» интерпретируется как разделитель разделов, подразделы также включаются. Если заданоpath=/docs
, то подходят и такие пути, как/docs
,/docs/web
,/docs/web/http
.
Работа с cookie из JavaScript
Куки можно создавать через JavaScript при помощи свойства document.cookie
. Если флаг HttpOnly
не установлен, то и доступ к существующим cookies можно получить через JavaScript.
// получить cookie console.log(document.cookie);
PHPSESSID=m2iut9i59p73ld1c5q9j49c6t0; visitor=0d3749f09d222bea3b8f163937eb9bf1; lastvisit=1538919655
// установить cookie document.cookie = "some_name=some_value"; console.log(document.cookie);
PHPSESSID=m2iut9i59p73ld1c5q9j49c6t0; visitor=0d3749f09d222bea3b8f163937eb9bf1; lastvisit=1538919655; some_name=some_value
Функция getCookie()
Следующая функция возвращает cookie с именем name
:
// возвращает cookie с именем name, если есть, если нет, то undefined function getCookie(name) { var matches = document.cookie.match( new RegExp("(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)") ); return matches ? decodeURIComponent(matches[1]) : undefined; }
Функция setCookie()
function setCookie(name, value, options) { options = options || {}; var expires = options.expires; if (typeof expires == "number" && expires) { var d = new Date(); d.setTime(d.getTime() + expires * 1000); expires = options.expires = d; } if (expires && expires.toUTCString) { options.expires = expires.toUTCString(); } value = encodeURIComponent(value); var updatedCookie = name + "=" + value; for (var propName in options) { updatedCookie += "; " + propName; var propValue = options[propName]; if (propValue !== true) { updatedCookie += "=" + propValue; } } document.cookie = updatedCookie; }
Функция deleteCookie()
function deleteCookie(name) { // удаляем вызовом setCookie() с датой в прошлом setCookie( name, "", {expires: -1} ) }
Работа с cookie из PHP
Для сохранения cookie в браузере пользователя используется функция setcookie()
:
bool setcookie( string $name, string $value, int $expire, string $path, string $domain, bool $secure, bool $httponly );
Может принимать следующие параметры:
name
: имя cookie, которое будет использоваться для доступа к его значению.value
: значение или содержимое cookie — любой алфавитно-цифровой текст не более 4 кБайт.expire
(необязательный параметр): срок действия, после которого cookie уничтожаются. Если данный параметр не установлен или равен 0, то уничтожение cookie происходит после закрытия браузера.path
(необязательный параметр): путь к каталогу на сервере, для которого будут доступны cookie. Если задать «/», cookie будут доступны для всего сайта. Если задать, например,/docs
, cookie будут доступны из этого каталога и всех его подкаталогов (/docs/web
,/docs/web/http
). По умолчанию значением является текущий каталог, в котором устанавливаются cookie.domain
(необязательный параметр): задает домен, для которого будут доступны cookie. Если это домен второго уровня, например,server.com
, то cookie доступны для всего сайтаserver.com
, в том числе и для его поддоменов типаblog.server.com
. Если задан поддоменblog.server.com
, то cookie доступны только внутри этого поддомена.secure
(необязательный параметр): указывает на то, что значение cookie должно передаваться по протоколу HTTPS. Если заданоtrue
, cookie от клиента будет передано на сервер, только если установлено защищенное соединение. По умолчанию параметр равенfalse
.httponly
(необязательный параметр): если равноtrue
, cookie будут доступны только через HTTP протокол. То есть cookie в этом случае не будут доступны из JavaScript. По умолчанию параметр равенfalse
.
Чтобы получить cookie, можно использовать глобальный массив $_COOKIE
. Для удаления cookie достаточно в качестве срока действия указать какое-либо время в прошлом:
setcookie('lastvisit', '', time() - 3600);
Чтобы к идентификатору сессии PHPSESSID
не было доступа из JavaScript, нужно отредактировать файл php.ini
:
; Name of the session (used as cookie name). ; http://php.net/session.name session.name = PHPSESSID ; Whether or not to add the httpOnly flag to the cookie, which makes ; it inaccessible to browser scripting languages such as JavaScript. ; http://php.net/session.cookie-httponly session.cookie_httponly = 1
Можно также использовать функцию ini_set()
, чтобы установит флаг HttpOnly
уже во время выполнения приложения:
ini_set('session.cookie_httponly', 1); session_start();
Еще одни способ изменить флаг HttpOnly
— вызов функции session_set_cookie_params()
перед session_start()
:
session_set_cookie_params(/*...*/); session_start();
Установить флаг Secure
для PHPSESSID
из php.ini
:
; http://php.net/session.cookie-secure session.cookie_secure = 1
Установить флаг во время работы приложения:
ini_set('session.cookie_secure', 1); session_start();
session_set_cookie_params(/*...*/); session_start();
- LocalStorage и SessionStorage
- Утилита командной строки Wget
- RESTfull API приложение на фреймворке Express.js
- Расширение REST Client для VS Code
- Магазин на Laravel 7, часть 19. Панель управления, добавляем редактор для страниц сайта
- WordPress. Создание одностраничного сайта
- Yii2. Отправка данных AJAX
Поиск: Cookie • HTTP • HTTPS • JavaScript • PHP • Web-разработка • expire • httponly • localStorage • php.ini • secure • sessionStorage • setcookie