微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

将现有的密码哈希转换为Devise

如何解决将现有的密码哈希转换为Devise

| 我正在尝试将现有的Admin模型转换为Devise。我们已经有一个密码哈希,但显然与Devise不兼容。我想做的是接受登录表单,并对照加密的密码检查提供的密码。如果不正确,请使用旧的哈希检查密码,如果匹配,则清空旧的password_hash字段,并将Devise的密码设置为提供的密码并保存模型。 前进的最佳方法是什么?我怀疑可能需要在自定义控制器中重写某些内容,但是我不确定如何继续。     

解决方法

您可以让Devise使用新的加密方案来完成加密密码的“艰苦工作”,如https://gist.github.com/1704632所示:
class User < ActiveRecord::Base
  alias :devise_valid_password? :valid_password?

  def valid_password?(password)
    begin
      super(password)
    rescue BCrypt::Errors::InvalidHash
      return false unless Digest::SHA1.hexdigest(password) == encrypted_password
      logger.info \"User #{email} is using the old password hashing method,updating attribute.\"
      self.password = password
      true
    end
  end
end
    ,在Devise中使用bcrypt加密器,这就是我对遗留数据所做的最终结果: 在models / user.rb中
# Because we have some old legacy users in the database,we need to override Devises method for checking if a password is valid.
# We first ask Devise if the password is valid,and if it throws an InvalidHash exception,we know that we\'re dealing with a
# legacy user,so we check the password against the SHA1 algorithm that was used to hash the password in the old database.
alias :devise_valid_password? :valid_password?
def valid_password?(password)
  begin
    devise_valid_password?(password)
  rescue BCrypt::Errors::InvalidHash
    Digest::SHA1.hexdigest(password) == encrypted_password
  end
end
如您所见,devise遇到无效哈希时会抛出InvalidHash异常,这在对旧用户进行身份验证时会发生。 我用它回退到用于创建原始旧式哈希的哈希算法。 虽然它不会更改密码,但是可以根据需要将其简单地添加到方法中。     ,首先,您需要将password_salt和encryption_password复制到新的对象模型中 使用此方法是因为我必须将数据库用户导出到另一个旧的应用程序,  应用正在使用devise 1.0.x,新应用正在使用2.1.x
Class User < ActiveRecord::Base
 alias :devise_valid_password? :valid_password?
    def valid_password?(password)
      begin
        devise_valid_password?(password)
      rescue BCrypt::Errors::InvalidHash
        salt = password_salt
        digest = nil
        10.times { digest = ::Digest::SHA1.hexdigest(\'--\' << [salt,digest,password,nil].flatten.join(\'--\') << \'--\') }
        digest
        return false unless digest == encrypted_password
        logger.info \"User #{email} is using the old password hashing method,updating attribute.\"
        self.password = password
        self.password_salt = nil # With this you will knew what object already using the new authentication by devise
        self.save
        true
      end
    end
end
    ,如果您不使用SHA512,则解决方案比moeffju的SHA1解决方案要复杂得多:
def valid_password?(password)
  if has_legacy_password?
    return false unless valid_legacy_password?(password)
    convert_legacy_password!(password)
    true
  else
    super(password)
  end
end

protected

def has_legacy_password?
  password_salt.present?
end

def convert_legacy_password!(password)
  self.password = password
  self.password_salt = nil
  self.save
end

def valid_legacy_password?(password)
  stretches = 10
  salt = password_salt
  pepper = nil
  digest = pepper

  stretches.times do
    tokens = [salt,pepper]
    digest = Digest::SHA512.hexdigest(\'--\' << tokens.flatten.join(\'--\') << \'--\')
  end

  Devise.secure_compare(encrypted_password,digest)
end
确保将
stretches
pepper
替换为用于加密密码的值。     ,按照Thomas Dippel的说明,我已提出要更新密码的要点: https://gist.github.com/1578362
    # Because we have some old legacy users in the database,so we check the password against the SHA1 algorithm that was used to hash the password in the old database.
#SOURCES OF SOLUTION:
# http://stackoverflow.com/questions/6113375/converting-existing-password-hash-to-devise
# https://github.com/binarylogic/authlogic/blob/master/lib/authlogic/crypto_providers/sha512.rb
# https://github.com/plataformatec/devise/blob/master/lib/devise/encryptors/authlogic_sha512.rb

alias :devise_valid_password? :valid_password?
def valid_password?(password)
  debugger
  begin
    devise_valid_password?(password)
  rescue BCrypt::Errors::InvalidHash
    stretches = 20
    digest = [password,self.password_salt].flatten.join(\'\')
    stretches.times {digest = Digest::SHA512.hexdigest(digest)}
    if digest == self.encrypted_password
      #Here update old Authlogic SHA512 Password with new Devise ByCrypt password
      # SOURCE: https://github.com/plataformatec/devise/blob/master/lib/devise/models/database_authenticatable.rb
      # Digests the password using bcrypt.
      # Default strategy for Devise is BCrypt
      # def password_digest(password)
      # ::BCrypt::Password.create(\"#{password}#{self.class.pepper}\",:cost => self.class.stretches).to_s
      # end
      self.encrypted_password = self.password_digest(password)
      self.save
      return true
    else
      # If not BCryt password and not old Authlogic SHA512 password Dosn\'t my user
      return false
    end
  end
end 
    

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。