Как в Rails уничтожить сессию при закрытии браузера?

Я просматриваю Railstutorial Майкла Хартла и застрял на упражнении 9.6.2. Я искал в Интернете и использовал этот код в своем помощнике по сеансам:

module SessionsHelper

  def sign_in(user)

    session[:user_id] = user.id
    self.current_user = user
  end

  def current_user=(user)
    @current_user = user
  end

  def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
  end

  def signed_in?
    !current_user.nil?
  end

  def sign_out
    session[:user_id] = nil
    self.current_user = nil
  end
end

Я нашел его в Интернете по адресу: http://www.nimweb.it/web-development/ruby-on-rails-web-development/ruby-on-rails-tutorial-exercise-9-6-2.-rails-session/

Однако пользователь не выходит из системы, когда браузер закрыт. У кого-нибудь еще есть решение для этого?


person djblue2009    schedule 26.07.2011    source источник


Ответы (5)


EDIT: Глядя на ссылку, которую вы дали, они пишут:

Мы также можем запустить сервер (с помощью «$ rails s») и проверить работу нашего нового сеанса без файлов cookie (нам следует выходить из системы каждый раз, когда мы закрываем браузер).< /эм>

(выделение добавлено)

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

Мой первоначальный ответ оставлен ниже для исторической ценности:


(извините, если это слишком общее, я предполагаю, что вы не видите общей картины)

По сути, в Интернете используется модель, основанная на вытягивании — клиенты делают запросы на сервер.

Вы не можете «заставить» клиента закрыть сеанс, поскольку закрытие сеанса — это действие, которое клиент должен запросить у сервера (например, путем выхода из системы).

Поэтому обычно сеансы имеют период ожидания, который регулярно проверяется. Каждый сеанс имеет «время начала», хранящееся в базе данных, а слишком старые сеансы удаляются.

Тем не менее, в javascript может быть какой-то способ обнаружить событие закрытия браузера и сделать попытку закрыть сеанс. Но нет никаких гарантий — пользователь всегда может принудительно завершить процесс браузера, оставив сервер в полном неведении.

Короче говоря, вы не можете полагаться на то, что клиент закроет сеанс. Тайм-аут, вероятно, ваш лучший вариант.

person jwd    schedule 26.07.2011
comment
Стоит отметить, что если параметр Expires не указан, срок действия файла cookie по умолчанию истекает при закрытии браузера (в большинстве пользовательских агентов). - person Jeremy Roman; 27.07.2011
comment
Хороший момент, хотя просто для ясности: это не закрывает старый сеанс (с точки зрения сервера), а просто вызывает открытие нового в следующий раз. - person jwd; 27.07.2011

Я застрял на одном и том же упражнении во время прохождения урока. Если вы использовали Firefox и решили сохранить вкладки, а затем выйти, браузер, по-видимому, сохранит все данные вашего сеанса при повторном запуске браузера. Это означает, что информация о пользователе, сохраненная в файле cookie сеанса, также будет восстановлена, и, следовательно, пользователь будет входить в систему после закрытия браузера. Я не думаю, что другие браузеры (например, Chrome) ведут себя так же. Поэтому быстрый тест — использовать другой браузер и посмотреть, будет ли работать ваш код. Надеюсь это поможет.

person rubynewbie    schedule 02.03.2012
comment
Я протестировал свой Chrome (версия 20), и он сохранит сеанс после его закрытия. - person lulalala; 27.07.2012

Прежде всего, нужно выяснить, какое хранилище сеансов вы используете, чтобы избежать «путаницы». Я предполагаю, что в упражнении используется хранилище файлов cookie по умолчанию, но, конечно, вы могли уже изменить его на активное хранилище записей (или любое другое хранилище, которое хранит данные на сервер).

Проверьте файл config/initializers/session_store.rb, чтобы узнать, какое хранилище сеансов используется. Предполагая, что вы ничего не меняли в магазине, он должен быть настроен на :cookie_store, в этом случае вам не нужно ни о чем беспокоиться, так как файлы cookie на стороне клиента используются для хранения данных сеанса, и срок действия этих файлов cookie по умолчанию истекает после закрытия браузера (они так называемые «сеансовые» файлы cookie, просто для ясности, сеанс здесь относится к файлу cookie, который присутствует до тех пор, пока ваш сеанс просмотра не будет сохраняться — закрытие браузера удаляет файл cookie сеанса). Конечно, это не вызывает какой-либо код на стороне сервера, такой как sign_out или session.destroy, при выходе из браузера, но, поскольку файл cookie содержит все данные сеанса и удаляется браузером, вы больше не можете получить к нему доступ, поэтому сеанс можно считать уничтоженным. .

Теперь с хранилищем сеансов на стороне сервера все становится сложнее, как упоминалось в предыдущем ответе "Вы не можете "заставить" клиента закрыть сеанс". Что делает большинство людей, так это уничтожает сеансы с истекшим сроком действия вручную, например. http://guides.rubyonrails.org/security.html#session-expiry . Пример задачи rake https://gist.github.com/kares/919069

person kares    schedule 19.08.2011

Я читаю этот замечательный учебник прямо сейчас и получил то же задание около 30 минут назад. Джереми Роман точно ответил на вопрос в этой теме. Хотя он не дал пошагового ответа, то, что он упомянул, позволило мне найти ответ.

Теперь, чтобы быть более конкретным... Учитывая то, что Jeremy упомянул о сеансах, срок действия которых автоматически истекает после закрытия браузера, если для соответствующего файла cookie не указан атрибут «Expires», решение связано с следующий кусок кода:

app/helpers/session_helper.rb:

def sign_in(user)
  cookies.permanent.signed[:remember_token] = [user.id, user.salt]
  self.current_user = user
end

Согласно учебнику, описанный выше метод permanent установив для атрибута cookie «Expires» значение 20.years.from_now. Таким образом, это означает, что ваша сессия будет сохраняться в течение 20 лет, если вы не выйдете из системы явным образом или не удалите свой файл cookie.

Таким образом, чтобы истечь срок действия сеанса при закрытии браузера, вам просто нужно создать файл cookie без даты истечения срока действия, что сводится к простому опусканию permanent:

app/helpers/session_helper.rb:

def sign_in(user)
  cookies.signed[:remember_token] = [user.id, user.salt]
  self.current_user = user
end

Хотя могут быть и другие допустимые решения, которые для меня пока не очевидны (ведь я только начал изучать Rails), это выглядит очень просто — даже писать ничего не нужно — просто удалить permanent и вот! :)

person Iuliu Pascaru    schedule 02.12.2011

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

Проблема не в дизайне проблемы. Конечно, ожидается, что это упражнение будет выполнено с включенными файлами cookie. Скорее, проблема заключается в настройках браузера: «продолжить с того места, где вы остановились» или «открыть мои окна и вкладки с прошлого раза» при запуске браузера. Этот параметр поддерживает сеансы при закрытии браузера, а это именно то поведение, которое нам не нужно.

Эта проблема теперь упоминается в виде сноски в учебнике (глава 8, примечание 2). Автор говорит, что в отношении этой настройки браузера и связанных с ней бесконечных сессий:

...конечно, Rails не контролирует это поведение.

person Ryan Lue    schedule 04.04.2016