Rails 如何实现站点每个帐号只允许 1 个登录状态?

brookepowell · 2020年08月18日 · 最后由 msl12 回复于 2020年08月21日 · 1829 次阅读

如题,目前使用 sorcery 这个 gem 实现的用户登录注册管理,session 存在 redis 中。

请问实现思路大概是什么样子?

我的思路是每次请求都要查一下数据库。

虽然会多一次数据库查询,就当作是 User.find 吧,也不会耗费太多资源。

这是我做的一个多 session 管理的 demo,没有用任何的第三方库,有一个小 bug 但不影响你看我的实现思路:https://github.com/printfinn/rails-session-board

存数据库比较方便管理,也不会有多少性能损失。除了少部分不用登录的接口,都要在参数中携带 login_key,然后在 before_action 中验证 login_key 是否存在。登录相关的接口调用 SessionKey.create_with。

login_key 不必校验唯一性,用 uuid 生成,重复的概率可以忽略不计,省去一次 SQL 查询。数据表里加上 user_id 索引和 login_key 前缀索引,索引长度为 7 应该够用了。

class SessionKey < ApplicationRecord
  attr_accessor :login_key, :user_id

  def self.create_with(user:, relogin_flag: true)
    SessionKey.where(user_id: user.id).delete_all if relogin_flag
    SessionKey.create!(user_id: user.id, login_key: SecureRandom.uuid)
  end
end

以前用 redis 实现了个 per-user-per-session 的简单 demo(session 也存 redis)。在 redis 中加了个 hash 存 user_id 到 session_id 的映射,用户每次登陆成功后通过 user_id 拿到 session_id(若没有拿到,说明是没有在其他地方登陆),再根据 session_id 去更新 session。用户退出登陆时同理。基本就跟 session 存数据库时一个套路。需要知道框架或库是如何计算 session_id

如果是用 token 就好了

需要 登录 后方可回复, 如果你还没有账号请 注册新账号