Devise と Warden のソース コードを長い間調べた後、ようやく解決策を見つけました。
簡潔な答え:
User
これをクラスに追加します。
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
- から User クラスに混在していますDevise::Models::Authenticatable::ClassMethods
。正直なところ、それが実際に何をすべきかはわかりませんが、これは公開されたメソッドであり、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
た のインスタンスを返します。これは、本質的に を呼び出すことと同じです。(Devise はgem を使用して柔軟性を維持します。上記の方法は、ActiveRecord、Mongoid、またはその他の OrmAdapter 互換 ORM を使用しているかどうかに関係なく、変更なしで機能します。)OrmAdapter::ActiveRecord
User
to_adapter.get
User.find
orm_adapter
しかし、もちろん、User.find
default_scope 内でしか検索しないため、禁止されたユーザーを見つけることができません。呼び出すとクラスが直接to_adapter.klass
返され、それから呼び出してすべてのユーザーを検索し、禁止されているユーザーを Devise に表示することができます。したがって、作業行は次のとおりです。User
unscoped.find
record = to_adapter.klass.unscoped.find(key[0])
は Array (この場合は 1 つの要素) であり、Array を に渡すと Arrayが返されるため、key[0]
代わりにを渡していることに注意してください。key
key
find
またklass
、実際の Devise のソース コード内で呼び出すのは悪い考えであることに注意してくださいOrmAdapter
。しかし、どの ORM を使用しているか (Devise が知らないこと) を確実に知っている独自のアプリ内では、具体的に指定しても安全です。