设计 - bypass_sign_in没有active_for_authentication?打回来

时间:2018-05-18 06:33:12

标签: ruby-on-rails devise ruby-on-rails-5.1

我的应用程序中有非活动帐户的功能,用于处理此i覆盖active_for_authentication?方法,如下所示

def active_for_authentication?
  super && activated?
end

但在我的应用程序中,超级管理员也可以直接登录到其他用户帐户,无论是活动还是不活动

bypass_sign_in(User.find(resource.id))

我使用上面的方法通过登录,它允许我直接登录只有激活的用户,当我登录非激活用户时,它进入无限循环。

任何可以解决此问题的解决方案,或者在active_for_authentication?时运行bypass_sign_in回调?

2 个答案:

答案 0 :(得分:1)

当管理员登录到其他用户帐户时,您可以在会话中存储一些其他数据,这可以清楚地表明这是// service/user.js class UserService { async loginPass() { return User.findOne({ username }).exec(); } } // model/user.js import mongoose from 'mongoose'; import timeZone from 'mongoose-timezone'; const Schema = mongoose.Schema; const schema = new Schema({ model: { id: String, name: String, }, avatar: String, username: { type: String, required: true, trim: true, }, password: { type: String, required: true, }, count: { type: Number, default: 0, }, updated_at: { type: Date, default: Date.now, }, created_at: { type: Date, default: Date.now, }, }, { // remove __v versionKey: false, timestamps: { createdAt: 'created_at', updatedAt: 'updated_at', }, }); schema.index({ username: 1 }, { unique: true }); schema.index({ updated_at: -1, }); schema.plugin(timeZone); export default mongoose.model('User', schema); 模式。

super admin

不幸的是,您无法在Rails模型中访问def login_as(another_user) return unless current_user.super_admin? session[:super_admin_mode] = true bypass_sign_in(another_user) end ,但您可以将所需的会话信息存储在模型中可用的某个每请求全局变量中。解决方案可能是这样的:

session

在ApplicationController中:

module SessionInfo
  def self.super_user_mode?
    !!Thread.current[:super_user_mode]
  end

  def self.super_user_mode=(value)
    Thread.current[:super_user_mode] = value
  end
end

在模型中:

class ApplicationController < ActionController::Base
  before_filter :store_session_info

  private

  def store_session_info
    SessionInfo.super_user_mode = session[:super_admin_mode]
  end
end

此外,您应确保在超级用户注销时从def active_for_authentication? super && (activated? || SessionInfo.super_user_mode?) end 删除:super_admin_mode标志。也许它会自动发生,我不确定。也许您需要手动覆盖session方法(参见下面的示例)

Devise::SessionsController#destroy

另请阅读此内容,以便更好地了解 def destroy session[:super_admin_mode] = nil super end 如何处理会话Stop Devise from clearing session

答案 1 :(得分:0)

我最近遇到了一个类似的问题,我需要允许管理员以未在 Devise 中处于活动状态的普通用户身份登录。我想出了以下不涉及使用 Thread.current 的解决方案(在进一步在线研究之后,似乎使用 Thread.current 可能是解决此问题的一个不稳定的方法)。

您可以创建一个名为 ProxyUser 的 User 子类,它具有 active_for_authentication?返回真。像这样:

class ProxyUser < User
  # If you have a type column on User then uncomment this line below
  # as you dont want to expect ProxyUser to have type 'ProxyUser'
  #
  # self.inheritance_column = :_type_disabled
  
  devise :database_authenticatable
  
   def active_for_authentication?
    true
  end
 end

然后在控制器中你想要这样的东西:

proxy_user = ProxyUser.find(params[:user_id])

sign_in :proxy_user, proxy_user

此外,在您的路线中,您还需要设计以期待 ProxyUser,因此包括:

  devise_for :proxy_users

最后当你注销这个用户时(假设你可以在你的控制器代码中注销用户)确保告诉设计注销的范围,所以你会这样做

sign_out :proxy_user

最后请注意,在您的应用程序中,您可能希望在不同的地方使用 current_user(例如,如果您使用 CanCanCan 进行授权),现在当您以 proxy_user 身份登录时,您的应用程序将返回 current_user 为 nil。您的应用程序将有一个名为 current_proxy_user 的对象,它将成为您登录的 ProxyUser 对象。在这种情况下,有多种方法可以处理因 current_user 返回 nil 而导致的问题(包括覆盖应用控制器中的 current_user)。