简体   繁体   English

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

[英]Rails 3 + Devise: log out user after timeout

In my app I set Devise to timeout a session after 30 minutes. 在我的应用程序中,我将Devise设置为在30分钟后超时。 Which works fine... the user has to log in again after that time. 哪个工作正常...用户必须在此之后再次登录。 My only problem is that devise apparently doesn't use the destroy action in the session controller after a session has timed out. 我唯一的问题是,在会话超时后,设计显然不会在会话控制器中使用销毁操作。 So the attribute :signed_in for the user isn't set to 'false'. 因此,用户的属性:signed_in未设置为“false”。 So even after a session has timed out this user is still displayed as online. 因此,即使会话超时后,该用户仍显示为在线。 Is there a way to destroy the session after the timeout or set the signed_in attribute to false after a certain time and on browser close? 有没有办法在超时后销毁会话或在一段时间后在浏览器关闭后将signed_in属性设置为false?

My destroy action in session controller: 我在会话控制器中的销毁操作:

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

I'm not exactly an expert on Devise but I suspect this is because of the stateless nature of HTTP. 我不是Devise的专家,但我怀疑这是因为HTTP的无状态特性。 Devise only knows a session is timed out when the user tries to access a page again after your timeout length and will likely only call the destroy method when a user actually logs out and the destroy method is called on the session controller. 当用户在超时长度后尝试再次访问页面时,Devise只知道会话超时,并且当用户实际注销并且在会话控制器上调用destroy方法时,可能只调用destroy方法。

In order to achieve what you are likely looking for, you would need to run a background process that sweeps for old sessions and then manually calls the destroy method (or does something similar). 为了实现您可能正在寻找的东西,您需要运行一个后台进程来扫描旧会话,然后手动调用destroy方法(或执行类似的操作)。

With the new Devise version it works as follows to have an accurate online/offline status: 使用新的Devise版本,其工作方式如下,以获得准确的在线/离线状态:

put this in your application_controller: 把它放在你的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

With every action the app checks if the last request was over 1min ago, if yes, he updates the user attribute. 对于每个操作,应用程序检查最后一个请求是否超过1分钟,如果是,则更新用户属性。

put this in user.rb: 把它放在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

you can then use the signed_in? 然后你可以使用signed_in? method to determine a users online status. 确定用户在线状态的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM