通过user_id查找并终止所有活动会话



我在Rails 6应用程序上使用基于cookie的会话,设置如下:

Rails.application.config.action_dispatch.cookies_serializer = :marshal
Rails.application.config.session_store :cookie_store, expire_after: 14.days

用户更改密码后,我想终止他所有的活动会话,这些会话可能在其他浏览器和/或设备中。类似这样的东西:

ActionDispatch::Session::CookieStore.where(user_id: session[:user_id]).destroy_all

只有这些方法对于CookieStore来说并不是真正有效的方法。知道如何做到这一点吗?

不幸的是,无论会话存储方式如何,都无法通过会话实现这一点。

要做到这一点,你必须将服务器上的活动登录列表保存在单独的DB表中,并删除这些记录,例如:

您可以创建新表,例如logins,其中包含列user_idtoken。每次用户登录时,您都会在此表中创建新记录,然后将user_idtoken保存到会话:

def login
# ...
# user authorization code
# ...
login = user.logins.create(token: SecureRandom.uuid)
session[:user_id] = login.user_id
session[:user_token] = login.token
end

每次从会话加载用户时,您都必须执行两个步骤:

  1. 通过ID查找用户
  2. 检查user_token的有效性
def authorized_user
@authorized_user ||= begin
login = Login.find_by(user_id: session[:user_id], token: session[:user_token])
return if login.blank?

login.user
end
end

现在,每次您想注销用户时,只需要从登录表中删除相应的记录。

在您想要从所有其他设备注销用户的情况下,您只需要执行以下代码:

authorized_user.logins.where.not(token: session[:user_token]).delete_all

你就完了。

当然,这只是一个简单的例子,你也可以对代币进行哈希或加密,所以它们不是直接可读的,或者你可以添加到期日期,并在超过日期时自动注销用户,等等

最新更新