На главную

Cookie sharing

Теория

Cookie - это заголовок, который браузер отправляет автоматически вместе с каждым запросом. Cookie устанавливаются для определённого домена. Соответственно, и отправятся они на тот домен для которого установлены.

Однако одни и те же Cookie можно использовать для домена и его поддоменов. Для того, чтобы такое стало возможным, Cookie нужно установить для домена с лидирующей точкой. Например example.com будет отправляться только на example.com. А .example.com будет отправляться и на subdomain.example.com в том числе.

Здесь есть нюансы (выдержка из ответа на stackoverflow):

Согласно стандарту, In RFC 2109 домен без лидирущий точки означает, что кука не может быть использована на поддоменах. и только домет с лидирущей точкой позволяет использовать одни и теже куки на поддоменах Согласно более новой спецификации RFC 6265, лидирующая точка игнорируется, и куки для домена без точки может быть использована на поддоменах.

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

При этом домены .example.com и example.com не эквиваленты. То есть вы можете получить в браузере сразу 2 Cookie, одну для домена с точкой, другую для домена без.

К практике

Допустим, если вы хотите разрешить использовать одну и ту же Cookie для поддоменов в проекте Rails. Для этого нужно указать domain: :all явно:

cookies.signed[:user_id] = { value: user.id, domain: :all }

Это будет эквивалентно установке user_id для домена .example.com. (Разумеется, это будет тот домен, на котором размещён проект)

Не забудьте указать домен при удалении куки:

cookies.delete(:user_id, domain: :all)

Дальше — сложности. Если это был уже существующий проект, и вы ранее полагались на Cookie только для основного домена, то в браузере теперь будут 2 записи, (да, одна для домена с точкой, другая для домена без).

Поэтому удалять их надо обе.

Например, если они отвечают за аутентификацию, пользователь не сможет выйти с сайта. Однако Rails не удалит куку с одним и тем же именем дважды, если вы последовательно вызовете 2 строчки кода. (так написан исходный код Rails, по крайней мере в 5й версии).

То есть конструкция видаЖ

cookies.delete(:user_id, domain: :all)
cookies.delete(:user_id)

не поможет.

Если пользователей много, то объяснять им, что "вам надо почистить куки" бесполезно. Что делать?

Вариант А

Переименовать cookie и всех разлогинить

Вариант Б

Использовать грязный трюк двойной redirect:

def logout
  cookies.delete(:user_id, domain: :all)
  redirect_to logout_domain_path
end

def logout_domain
  cookies.delete(:user_id, domain: nil)
  redirect_to root_path
end

Вариант В

Дописать Rails, возможно это до сих пор не исправлено.

На главную