Сессии пересекаются. Рубин на рельсах

У меня есть приложение, которое использует devise для аутентификации. Rails 3 на ruby ​​1.9.2 с пассажиром поверх nginx.

Вот моя проблема: я заметил, что иногда мои сеансы пересекаются. Войдя в систему как один пользователь, я иногда становлюсь другим пользователем. Это действительно ужасная проблема. Мне удалось остановить его, используя хранилище сеансов active_record. Но я в тупике относительно того, где это могло произойти. Это происходит как при использовании хранилища cookie, так и при использовании хранилища memcached. Я не уверен, с чего начать отладку. Я просмотрел весь свой код, и я только читаю «current_user», а не пишу. У меня нет кода, хранящего элементы в сеансе.

Может ли кто-нибудь дать мне предложения относительно того, где или как это может происходить?

Обновление:

Я устанавливаю div в верхней части страницы, чтобы сбрасывать содержимое сеанса при каждом запросе. Это не просто переключение пользователя, это весь сеанс. Есть несколько фиктивных переменных, которые я установил в сеансе, просто чтобы посмотреть, что произойдет. Когда сеансы пересекаются (пользователь A становится пользователем B), пользователь A теперь видит фиктивные переменные, которые были у пользователя B. И Пользователь B вышел из системы.

ОБНОВЛЕНИЕ 2

Здесь я нашел еще один вопрос о переполнении стека, который описывает точно такую ​​же проблему: other-users-session">Что в Rails может привести к тому, что у пользователя будет сеанс другого пользователя?

Кажется, это может быть проблема с пассажиром? Но что более важно, почему это вообще происходит? Это НАСТОЯЩАЯ большая проблема. Как мне положить этому конец?

ОБНОВЛЕНИЕ 3

Сейчас я использую Unicorn для обслуживания своего приложения. Я установил config.threadsafe! и начал использовать исключительно сеансы активной записи. Нет больше сеансов memcached. Проблема исчезла. По крайней мере, я могу перестать рвать на себе волосы, потому что дыра в безопасности закрыта.

Я все еще хотел бы знать, что именно было причиной этого. В большинстве туториалов показано, как настроить пассажира с методом порождения по умолчанию. Естественно, я думаю, что memcached лучше подходит для управления сессиями по сравнению с другими методами. Особенно в среде с несколькими серверами приложений.

Обновление 4

Итак, последнее и последнее обновление. Это была проблема с разветвленными процессами, использующими одно и то же соединение memcached. Я исправил это, используя клиент dalli memcached и сбросив соединение в обратном вызове after_fork либо для единорога, либо для пассажира.


person demersus    schedule 21.01.2011    source источник
comment
Вы используете разных пользователей в одном и том же браузере? Или это просто совершенно случайный другой пользователь, которого вы не использовали в последнее время?   -  person Chris Kimpton    schedule 21.01.2011
comment
Не вошли в систему с отдельными пользователями в том же браузере. Это происходит даже в отдельных сетях. Пользователь А может стать пользователем Б. Даже если они находятся в разных местах. Это происходит случайным образом, и единственное, что я обнаружил, это то, что они оба должны войти в систему, чтобы это произошло.   -  person demersus    schedule 21.01.2011
comment
Возможно ли, что это может быть проблема с пассажиром? Кэширует ли devise/warden переменную current_user?   -  person demersus    schedule 21.01.2011
comment
Я бы добавил отладку везде... может быть, какой-то фрагмент кода не является потокобезопасным?   -  person rogerdpack    schedule 21.01.2011


Ответы (2)


Готов поспорить, что вы используете умный спавн Passenger (по умолчанию) и стали жертвой Spawning Gotcha.

Установите для PassengerSpawnMethod значение «консервативный» и посмотрите, исчезнет ли это. Это легко объясняет случай memcache, если вы не защищаете от него. Предположительно аналогичная проблема в разработке (или вашем коде).

Вы видите, что сеансы пересекаются между физическими серверами или только на одном сервере?

person user510365    schedule 23.01.2011
comment
В настоящее время я запускаю пассажира с методом нереста по умолчанию на одной машине. Текущая переменная сеанса не должна правильно очищаться между запросами. Я не могу себе представить, с настройками по умолчанию это не было замечено другими людьми как проблема. Я попробую консервативный метод спавна, но он сводит на нет некоторые преимущества использования пассажира. - person demersus; 24.01.2011
comment
Если бы это действительно была переменная сеанса, это также повлияло бы на сеансы ActiveRecord, верно? Так что я не думаю, что это так. Подобные проблемы с memcache ЯВНО упоминаются в документации пассажира (в этой подводной лодке), поэтому вы должны убедиться, что у вас есть это, а если нет, исправьте и вернитесь к сеансам memcache. Можете ли вы воспроизвести в среде разработки? - person user510365; 28.01.2011
comment
Эта проблема была временно решена с помощью сеансов ActiveRecord. Недавно я попытался использовать Unicorn для обслуживания приложения, и, похоже, это происходит и с Unicorn. - person demersus; 18.05.2011

Весьма вероятно, что эту ошибку можно исправить, обновившись до стоечного кэша 1.2 или выше. Вот что может происходить:

  1. Пользователь А запрашивает страницу. Создается сеанс, и в ответе возвращается заголовок Set-Cookie.
  2. Rack-cache неправильно кэширует заголовок Set-Cookie с идентификатором сеанса пользователя A.
  3. Пользователь B запрашивает ту же страницу, и Rack-Cache обслуживает кэшированный ответ, включая заголовок Set-Cookie с идентификатором сеанса пользователя A.

Эти два билета обсуждают эту проблему: https://github.com/rails/rails/issues/476 и https://github.com/rtomayko/rack-cache/pull/52

Наконец, эта проблема упоминается в примечаниях к выпуску для стоечного кэша 1.2: https://github.com/rtomayko/rack-cache/blob/master/CHANGES

Также обратите внимание, что даже если вы НЕ используете хранилище сеансов файлов cookie, ID сеанса по-прежнему хранится в файле cookie, поэтому эта ошибка все еще может беспокоить вас, даже если вы не используете хранилище файлов cookie.

Надеюсь это поможет.

Йоханнес

person Johannes Fahrenkrug    schedule 06.02.2013