10

我一直在使用 Devise,并依靠用户模型的 last_sign_in_at 来确定我的客户是否在 X 天内没有返回。但是,我最近发现 last_sign_in_at 仅在发生实际表单登录事件时才更新,而不是在用户自动登录时更新,因为包含了可记住的。

如果要确保每次用户登录(新的浏览器会话)时更新 last_sign_in_at,无论他们是使用表单登录还是由可记住的 cookie 自动登录,我将如何在设计兼容方式?

4

5 回答 5

15

采取 Matthew 的解决方案,我认为代码应该如下(注意 session[:logged_signin] 之前的 not-operator):

before_filter :update_last_sign_in_at

protected

def update_last_sign_in_at
  if user_signed_in? && !session[:logged_signin]
    sign_in(current_user, :force => true)
    session[:logged_signin] = true
  end
end
于 2012-08-18T19:23:59.780 回答
6

可跟踪的钩子来自Warden 的 after_set_user钩子——您可以做的很容易解决这个问题的方法是设置一个 before_filter 来调用sign_in

这可以优化,但测试看看是否使用

before_filter proc{ sign_in(current_user, :force => true) }

更新 last_signed_in_at 时间戳。

于 2012-01-09T20:12:47.470 回答
2

Devise: rememberable 表示 last_sign_in_at 不被 trackable 更新

扩展之前的解决方案,他们的问题是如果用户正常登录,他们将“登录两次”。它将设置last_sign_in_at为与 . 相同(或几乎相同)的值current_sign_in_at。在我的网站上,我习惯于last_sign_in_at让用户知道自他们上次访问该网站以来发生了什么,因此我需要它有点准确。此外,它还会记录 +1 登录计数。

此外,有些人(比如我自己)将浏览器窗口打开了好几天而没有关闭它(因此从不清除会话标志)。出于度量目的等,如果此类用户行为有时会刷新current_sign_in_at时间,这可能会很有用。

以下变体将解决这些问题。

class ApplicationController < ActionController::Base
  before_filter :update_sign_in_at_periodically
  UPDATE_LOGIN_PERIOD = 10.hours

  protected

  def update_sign_in_at_periodically
    if !session[:last_login_update_at] or session[:last_login_update_at] < UPDATE_LOGIN_PERIOD.ago
      session[:last_login_update_at] = Time.now
      sign_in(current_user, :force => true) if user_signed_in?
    end
  end
end

但是,当我使用 Devise 3.2.4 尝试上述操作时,当它通过 cookie 自动登录(登录计数 +1 并current_sign_in_at正在设置)时,我确实获得了新的登录。因此,我只剩下希望跟踪定期更新的问题,即使对于保持会话打开的用户也是如此。

class ApplicationController < ActionController::Base
  before_filter :update_sign_in_at_periodically
  UPDATE_LOGIN_PERIOD = 10.hours 

  protected 

  def update_sign_in_at_periodically
    # use session cookie to avoid hammering the database
    if !session[:last_login_update_at] or session[:last_login_update_at] < UPDATE_LOGIN_PERIOD.ago
      session[:last_login_update_at] = Time.now
      if user_signed_in? and current_user.current_sign_in_at < 1.minute.ago # prevents double logins
        sign_in(current_user, :force => true)
      end
    end
  end
end
于 2016-02-23T17:52:19.023 回答
1

application_controller你可以设置一个before_action检查当前用户的 current_sign_in_at 是否比 X 前更长。如果是,则使用sign_in(current_user, force: true)它更新 current_sign_in_at。

before_action :update_last_sign_in_at

def update_last_sign_in_at
   return unless user_signed_in? && current_user.current_sign_in_at < 12.hours.ago
   sign_in(current_user, force: true)
end

我使用它来检测非活动用户(未登录 6 个月)并删除它们。#GDPR

于 2018-05-24T10:04:45.937 回答
-1

AFAIK 您也可以update_tracked_fields!在该current_user模型上使用。

于 2015-01-23T12:08:14.533 回答