ruby-on-rails - 当 Devise 用户超出我的默认范围时,如何允许他们登录?

标签 ruby-on-rails activerecord devise warden default-scope

我有一个 Rails 4 应用程序,它使用 Devise 3.4 进行身份验证,我已经定制了禁止用户的能力(使用简单的 bool 列 users.banned,默认为 false)。 User型号也有default_scope它只返回非禁止用户。

这就是问题所在 - 我仍然希望我的被禁止用户能够登录,即使他们在登录后无法做任何事情。(他们基本上只是看到一个页面说“你已被禁止”)。但似乎 default_scope正在绊倒设计。当您登录或打电话时,例如authenticate_user! , Devise 尝试使用基本的 ActiveRecord 方法之一来查找当前用户,例如 findfind_by ,但不能,因为它们位于默认范围之外。因此,Devise 得出用户不存在的结论,并且登录失败。

如何让设计忽略默认范围?

最佳答案

之后长 在 Devise 和 Warden 源代码中四处挖掘的时间,我终于找到了解决方案。

简短的回答:

将此添加到 User类(class):

def self.serialize_from_session(key, salt)
  record = to_adapter.klass.unscoped.find(key[0])
  record if record && record.authenticatable_salt == salt
end

(请注意,我只为 ActiveRecord 测试过这个;如果您使用不同的 ORM 适配器,您可能需要更改方法的第一行......但是我不确定其他 ORM 适配器是否甚至有这个概念的“默认所以

长答案:
serialize_from_session从 - Devise::Models::Authenticatable::ClassMethods 混入 User 类.老实说,我不确定它实际上应该做什么,但它是一个公共(public)方法,并且在 Devise API 中记录(非常稀疏),所以我认为它在没有警告的情况下从 Devise 中删除的可能性不大。

这是 Devise 3.4.1 的原始源代码:
def serialize_from_session(key, salt)
  record = to_adapter.get(key)
  record if record && record.authenticatable_salt == salt
end

问题在于 to_adapter.get(key) . to_adapter返回 OrmAdapter::ActiveRecord 的实例缠绕User类和 to_adapter.get与调用 User.find 基本相同. (Devise 使用 orm_adapter gem 来保持它的灵 active ;无论您使用 ActiveRecord、Mongoid 还是任何其他与 OrmAdapter 兼容的 ORM,上述方法都无需修改即可工作。)

但是,当然,User.find仅在 default_scope 内搜索,这就是为什么它找不到我被禁止的用户的原因。调用to_adapter.klass返回 User直接上课,然后我可以调用unscoped.find搜索 全部 我的用户并使被禁止的用户对设计可见。所以工作线是:
record = to_adapter.klass.unscoped.find(key[0])

请注意,我正在传递 key[0]而不是 key , 因为 key是一个数组(在这种情况下只有一个元素)并将一个数组传递给 find将返回一个数组,这不是我们想要的。

另请注意,调用 klass在真正的 Devise 源代码中将是一个坏主意,因为这意味着您失去了 OrmAdapter 的优势.但是在您自己的应用程序中,您可以肯定地知道您正在使用哪个 ORM(Devise 不知道的东西),具体来说是安全的。

关于ruby-on-rails - 当 Devise 用户超出我的默认范围时,如何允许他们登录?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29813744/

相关文章:

Mysql2::错误:字段 'teacherid' 没有默认值:INSERT INTO `students` VALUES ()

ruby-on-rails - 使用 vim 从现有标记 block 轻松创建 Ruby on Rails 部分

mysql - has_many 总和事件记录

ruby-on-rails - 用于注册 Spree Commerce 的电子邮件验证

ruby-on-rails - Rails - 设计 - 处理 - devise_error_messages

ruby-on-rails - rails : How to populate Db with data without migrations getting in the way?

ruby-on-rails - rails 4 : Moving Active Record generated collections from view to model

ruby-on-rails - 多个服务器上 Rails 中奇怪的 ActiveRecord 时区行为

ruby-on-rails - Rails Postgres 查询排除包含连接上三个记录之一的任何结果

ruby-on-rails-4 - 我的表单输入字段不适用于 Materializecss