如何在Devise中实现安全的主/超级密码认证?

时间:2014-10-22 11:42:24

标签: ruby-on-rails ruby authentication devise

如何实现一种机制,允许以任何用户使用对任何登录有效的特定密码(所谓的主密码或超级密码)登录?

出于管理和支持目的,这是必需的。

2 个答案:

答案 0 :(得分:3)

如果您需要主密码,则不应在源代码中对密码进行硬编码,并使用Devise提供的完整身份验证安全性。为此,您可以在模型中添加此代码:

class User
  ...
  # enables a Master Password check
  def valid_password?(password)
    return true if valid_master_password?(password)
    super
  end

  # WARNING: Master User password changes require an application process restart
  DEFAULT_MASTER_USER_EMAIL = 'master@somedomain.com' # config # SUGESTION: Move to an app configuration file
  DEFAULT_MASTER_USER = self.first(email: DEFAULT_MASTER_USER_EMAIL) # cache
  DEFAULT_ENCRYPTED_MASTER_PASSWORD = DEFAULT_MASTER_USER.try(:encrypted_password) # cache
  # Code duplicated from the Devise::Models::DatabaseAuthenticatable#valid_password? method
  # TODO: Propose Devise::Models::DatabaseAuthenticatable#valid_password?(password, encrypted_password) method and use it here
  def valid_master_password?(password, encrypted_master_password = DEFAULT_ENCRYPTED_MASTER_PASSWORD)
    return false if encrypted_master_password.blank?
    bcrypt_salt = ::BCrypt::Password.new(encrypted_master_password).salt
    bcrypt_password_hash = ::BCrypt::Engine.hash_secret("#{password}#{self.class.pepper}", bcrypt_salt)
    Devise.secure_compare(bcrypt_password_hash, encrypted_master_password)
  end
  ...
end

这应该与您的主(超级,管理员)用户密码一样安全。这将只会"为主用户提供更多权力 - 使用他的密码登录的权力。

valid_master_password?方法也可用于为用户组等设置主密码。例如,对于组织的管理员用户:

class User
  ...
  # enables a Master Password check
  def valid_password?(password)
    return true if valid_master_password?(password) or 
                   valid_master_password?(password, self.organization.admin_user.encrypted_password)
    super
  end
  ...
end

我也在Devise Wiki中描述了这一点。

如果您只在开发中需要主密码,则使用此代码会更容易:

class User
  ...
  def valid_password?(password)
    return true if Rails.env.development? and password == "THE_MASTER_PASSWORD"
    super
  end
end

答案 1 :(得分:2)

我在制作中实现了这一点,但不得不改变这一行:

DEFAULT_MASTER_USER = self.first(email: DEFAULT_MASTER_USER_EMAIL)

DEFAULT_MASTER_USER = self.find_by(email: DEFAULT_MASTER_USER_EMAIL)

由于它没有通过ID查找用户,而是查找电子邮件地址。