Предлагаю вашему вниманию небольшую заметку о работе с куками в Kohana v3. Наверняка вы знаете, что для этого в Ko3 имеется специальный хэлпер Cookie. Как обычно, сперва рассмотрим его методы.
Тут все привычно и понятно
set($name, $value, $expiration = NULL)
Устанавливает куку по имени$name
в значение$value
(на самом деле не совсем так, об этом позже). Параметр$expiration
необязательный, он предназначен для указания срока актуальности куки. Например, если установить$expiration
в 30, то получится время жизни 30 секунд от момента установки. Если параметр сделать равным нулю, то кука сохранится без времени жизни и удалится по окончании сессии браузера. Если же его вообще опустить, то будет взято значение по умолчанию — свойствоCookie::$expiration
. Изначально оно равно нулю, но так как оноpublic
, то его можно поменять под себя.
Если установка куки прошла успешно, возвращается TRUE, иначе FALSE.get($key, $default = NULL)
Возвращает куку по имени$key
, а если не найдена — значение$default
.delete($name)
Удаляет куку$name
. Происходит это следующим образом — текущее значение обнуляется, время жизни передается отрицательное (т.е. кука уже просрочена).Важно понимать, что при установке куки (классическим
setcookie()
илиCookie::set()
— без разницы) новое значение будет установлено только после перезагрузки страницы (точнее после отправки HTTP-заголовков). Текущее же значение так и останется нетронутым в глобальном массиве$_COOKIE
. Помните об этом, т.к.Cookie::set()
изменяет только будущую куку,Cookie::get()
пытается найти текущую, аCookie::delete()
удаляет как текущую, так и отправляемую.
Дополнительные параметры
В данном классе есть публичные статичные свойства, которые могут быть полезными при работе с куками. Одно из них (Cookie::$expiration
) я уже упомянул, вот прочие:
$path
(‘/‘ по умолчанию). Используется для указания пути, для которого доступна кука. Например:
Cookie::$path = '/'; // кука доступна для всего содержимого домена Cookie::$path = '/first/'; // кука видна только в папке first и ее содержимом
$domain
(NULL по умолчанию). Позволяет четко указать, для какого домена использовать куку. Например, для успешного использования кук поддоменами, надо указать имя родительского домена, предварив его точкой, например так:
Cookie::$domain = '.first.com'; // кука будет доступна в доменах first.com, second.first.com и т.д. Cookie::$domain = 'second.first.com'; // куки будут недоступны для домена first.com!!
$secure
(FALSE по умолчанию). По названию понятно, что используется для безопасной отправки кук. Заголовки с куками будут отправлены только если используется протокол HTTPS.$httponly
(FALSE по умолчанию). Это тоже опция безопасности. Если установить в TRUE, то доступ к кукам будет осуществляться только посредством HTTP-заголовков (т.е. отсекаются скриптовые языки, например JavaScript).
Изюминка
А зачем же тогда класс Cookie нужен, если он по сути не отличается от «родной» функции setcookie()
? Так вот, данный класс позволяет дополнительно шифровать куки, а точнее — подписывать их. Дело в том, что метод Cookie::set()
отправляет не переданное значение $value
, а более сложную конструкцию, состоящую из двух частей — собственно значение и его подпись.
Вот, например, как выглядит у меня кука по имени ‘test1‘ и значением 1:
8f72531079624b276ca56e21b3162a648ba20431~1
Первая часть (до тильды) — это и есть таинственная подпись, потом идет нешифрованное значение — единица. В чем смысл? Разработчики постарались обезопасить куки от подмены значения. Когда мы передаем в Cookie::set()
переменную, хэлпер формирует строковое значение из имени браузера ($_SERVER['HTTP_USER_AGENT']
), имени куки и нового значения и генерирует хэш от полученной строки. В результате получается подпись для куки.
Обратите внимание, что само по себе значение ни от кого не прячется — оно доступно, просто откиньте тильду. Но вот если кто-то попробует подменить значение, то сгенерированная заново подпись не совпадет с переданной в куке — так система определит подмену и просто отбросит куку.
Все вышеуказанные действия по формировании подписи осуществляются в методе salt($name, $value)
. Помимо вышеперечисленных «ингредиентов», перед хэшированием добавляется соль — значение параметра Cookie::$salt
. Это, как и в модуле Auth, позволяет усложнить возможный подбор подписи куки, т.к. сам алгоритм известен. Просто поменяйте значение по умолчанию на какое-то свое, и никто не сможет изменить ваши подписанные куки.
С подписью кук могут возникнуть проблемы, если в вашем проекте предполагается установка кук посредством JavaScript. Конечно, можно портировать алгоритм формирования подписи из php, чтобы кука не отбрасывалась после установки, но тогда вам придется опубликовать и соль, что неприемлимо. Если все же очень хочется писать куки из скрипта, есть вариант немного переписать класс Cookie, чтобы он мог принимать и неподписанные куки (определять по отсутствию тильды в значении).
На этом все, класс небольшой и совсем не страшный
Меня, как раз, это обязательное засаливания кук очень удивило в свой время. Это можно было сделать дополнительной опцией, но не обязательной.
А еще этот класс юзается при работе с сессией! А также саму сессию можно хранить в куках, конечно 4096 байт ограничение, но всё же…
Вообще много фреймов оборачивают нативные ф-ции пыха, тем самым допиливая и расширяя их.
Рекомендую всем юзать именно ф-ции фрейма, чем нативные, ну если они обернуты.
Согласен. Но вот как раз куки-сессии кохановские не очень радуют обязательным «засаливанием». Нужно писать свой класс, расширяющий функционал стандартных классов.
@Slaver О! я за тобой даже в твиттере следую ))
Я пока не имел трудностей с Куками в кохане, а вот с сессией, точнее Auth вот тут есть какие-то проблемки (вылетаю через несколько обновлений страниц)
С куками проблема может быть в том, если пробуешь использовать сторонние, в которых никакие секюрные штуки Kohana не задуманы. Я один раз сильно тупил, почему ничего не работает — потом понял. Т.е., повторюсь, обязательное добавление соли в куки — не очевидный процесс и совсем не обязательный.
ЗЫ За мной следят ))
@Максим Нагайченко
проблемы могут появиться если с Cookies потребуется работать через JS. WordPress, например, активно меняет значения Cookies таким образом .. с ‘подписью’ такие трюки работать уже не будут.
@stalker Ну везде можно найти ложку дёгтя. Можно конечно и извернуться… через аякс ))))
@Максим
не-не-не .. в этом случае я согласен с Slaver — лучше бы класс в Kohana был настраиваемым. из-за его отсутствия пришлось писать свой ‘велосипедик’
Собственно об этом я и писал в конце статьи. Только не совсем отказаться от подписывания, а комбинировать оба метода.