Rails 3 + Devise:超时后注销用户

时间:2011-03-09 14:58:43

标签: ruby-on-rails session devise

在我的应用程序中,我将Devise设置为在30分钟后超时。哪个工作正常...用户必须在此之后再次登录。我唯一的问题是,在会话超时后,设计显然不会在会话控制器中使用销毁操作。因此,用户的属性:signed_in未设置为“false”。 因此,即使会话超时后,该用户仍显示为在线。 有没有办法在超时后销毁会话,或者在一段时间后将浏览器关闭后将signed_in属性设置为false?

我在会话控制器中的销毁操作:

def destroy
  current_user.try("signed_in=", false); current_user.save
  signed_in = signed_in?(resource_name)
  sign_out_and_redirect(resource_name)
  set_flash_message :notice, :signed_out if signed_in
end

2 个答案:

答案 0 :(得分:4)

我不是Devise的专家,但我怀疑这是因为HTTP的无状态特性。设备只知道当用户在超时长度后再次尝试访问页面时会话超时,并且当用户实际注销并且在会话控制器上调用destroy方法时,可能只调用destroy方法。

为了实现您可能正在寻找的东西,您需要运行一个后台进程来扫描旧会话,然后手动调用destroy方法(或执行类似的操作)。

答案 1 :(得分:1)

使用新的Devise版本,其工作方式如下,以获得准确的在线/离线状态:

将它放在你的application_controller中:

before_filter :last_request

def last_request
 if user_signed_in?
  if current_user.last_request_at < 1.minutes.ago
    current_user.update_attribute(:last_request_at, Time.now)
  end
  if current_user.currently_signed_in = false
      current_user.update_attribute(:currently_signed_in, true)
  end
 end
end

对于每个操作,应用都会检查上一个请求是否超过1分钟,如果是,则更新用户属性。

将它放在user.rb中:

before_save :set_last_request

Warden::Manager.after_authentication do |user,auth,opts|
  user.update_attribute(:currently_signed_in, true)
end

Warden::Manager.before_logout do |user,auth,opts|
  user.update_attribute(:currently_signed_in, false)
end

def set_last_request
  self.last_request_at = Time.now
end

def signed_in?
 if self.currently_signed_in

  if self.timedout?(self.last_request_at.localtime)
    return false
  else
    return true
  end

 else
  false
 end
end

然后你可以使用signed_in?确定用户在线状态的方法。