4

我正在阅读 Michael Hartl 的 Railstutorial,我被困在练习 9.6.2 上。我在网上搜索并在我的 Sessions Helper 中使用了这段代码:

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/

但是,当浏览器关闭时,用户不会注销。还有其他人对此有解决方案吗?

4

5 回答 5

4

编辑:查看您提供的链接,他们写道:

我们还可以启动服务器(使用“$ rails s”)并验证没有 cookie 的全新会话的功能(每次关闭浏览器时我们都应该 注销)。

(重点补充)

因此,他们的解决方案是简单地关闭 cookie,这会导致每次访问都会创建一个新会话。他们并没有真正谈论在等式的服务器端删除旧会话。

我的原始答案保留在下面以获取历史价值:


(抱歉,如果这太笼统了,我假设您没有看到更大的图景)

从根本上说,Web 使用基于拉取的模型——客户端发出请求以在服务器上执行操作。

您不能“强制”客户端关闭会话,因为关闭会话是客户端必须从服务器请求的操作(例如:通过注销)。

因此,通常会话具有定期检查的超时期限。每个会话都有一个存储在数据库中的“开始时间”,并且太旧的会话将被清除。

也就是说,javascript 中可能有某种方法可以检测浏览器关闭事件并尽最大努力尝试关闭会话。但是不能保证——用户总是可以强行杀死浏览器进程,让服务器完全处于黑暗之中。

简而言之,您不能依赖客户端来关闭会话。超时可能是您最好的选择。

于 2011-07-26T23:05:48.477 回答
2

在阅读教程时,我被困在同一个练习中。如果您碰巧使用 Firefox 并决定保存选项卡然后退出,那么当您重新启动浏览器时,浏览器显然会保存您的所有会话数据。这意味着保存在会话cookie中的用户信息也将被恢复,因此在浏览器关闭后用户似乎已登录。我不认为其他浏览器(例如chrome)有同样的行为。所以一个快速的测试是使用另一个浏览器,看看你的代码是否可以工作。希望这可以帮助。

于 2012-03-02T03:34:03.343 回答
1

首先是清除您正在使用的会话存储以避免“混淆”。我猜该练习使用默认(cookie)存储,但当然您可能已经将其更改为活动记录存储(或将数据保存在服务器上的任何其他存储)。

检查您的config/initializers/session_store.rb文件以找出正在使用的会话存储。假设您没有更改应配置为的商店的任何内容:cookie_store,在这种情况下,您无需担心任何事情,因为客户端 cookie 用于存储会话数据,并且这些 cookie 默认在浏览器关闭后过期(它们'重新称为“会话”cookie,只是为了清楚,这里的会话确实是指存在的 cookie,直到您的浏览会话持续存在 - 关闭浏览器会删除会话 cookie)。当然,这不会调用任何服务器端代码,例如浏览器退出时的sign_outsession.destroy,但由于 cookie 保存了所有会话数据并被浏览器删除,因此您无法再访问它,因此可能会认为会话已被破坏......

现在,使用服务器端会话存储,这变得更加复杂,如前面的答案“您不能'强制'客户端关闭会话”中所述。大多数人所做的是手动销毁“过期”会话,例如http://guides.rubyonrails.org/security.html#session-expiry。示例 rake 任务https://gist.github.com/kares/919069

于 2011-08-19T06:33:51.490 回答
0

我现在正在阅读这个很棒的教程,并在大约 30 分钟前完成了同样的任务。 Jeremy Roman在这个帖子中准确地回答了这个问题。虽然他没有提供一步一步的答案,但他提到的事情让我想出了答案。

现在更具体地说...考虑到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上面的方法是将 'Expires' cookie 属性设置为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就可以了!:)

于 2011-12-02T13:48:13.977 回答
0

我知道这个答案晚了四年多一点,但我自己也遇到了同样的问题,并且在 SO 上以各种形式多次询问。我找到的唯一正确答案是here

问题不是问题的设计。当然,我们希望在启用 cookie 的情况下完成此练习。相反,问题出在浏览器设置中:启动浏览器时“从上次中断的地方继续”或“打开我上次的窗口和选项卡”。此设置使会话在浏览器关闭时保持活动状态,这正是我们不想要的行为。

这个问题现在在教程中作为脚注引用(第 8 章,注 2)。作者说,关于此浏览器设置及其随之而来的永无止境的会话,

...当然 Rails 无法控制这种行为。

于 2016-04-04T15:05:51.860 回答