将现有密码哈希转换为 Devise

发布于 2024-11-09 18:11:57 字数 211 浏览 2 评论 0原文

我正在尝试将现有的管理模型转换为设计。我们已经有了密码哈希,但它显然与 Devise 不兼容。我想做的是接受登录表单并根据加密密码检查提供的密码。如果不正确,请使用旧的哈希值检查密码,如果匹配,则清空旧的 password_hash 字段,并将 Devise 的密码设置为提供的密码并保存模型。

前进的最佳方式是什么?我怀疑我需要重写某些东西,也许是在自定义控制器中,但我不完全确定如何继续。

I'm trying to convert an existing Admin model to Devise. We already have a password hash but it's obviously not Devise compatible. What I would like to do is accept the login form and check the provided password against the encrypted password. If it's not correct, use the old hash to check the password and if it matches, empty the old password_hash field and set Devise's password to the provided password and save the model.

What's the best way to move forward? I suspect that I need to override something, perhaps in a custom controller, but I'm not entirely sure how to proceed.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

喜爱皱眉﹌ 2024-11-16 18:11:57

您可以让 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

You can let Devise do the "hard work" of encrypting the password with the new crypt scheme, as shown in 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
榆西 2024-11-16 18:11:57

在 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 异常,这会导致在对旧用户进行身份验证时就可以了。
我用它来回退到用于创建原始遗留哈希的哈希算法。

虽然它不会更改密码,但如果需要,可以简单地将其添加到方法中。

Using the bcrypt encryptor in Devise, this is what I ended up doing with my legacy data:

In 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

As you can see, devise throws an InvalidHash exception when it encounters an invalid hash, which it would do when authenticating a legacy user.
I use this to fall back to the hashing-algorithm used to create the original legacy hash.

It doesn't change the password though, but that could simply be added to the method if needed.

那一片橙海, 2024-11-16 18:11:57

首先,您需要将password_salt和encrypted_pa​​ssword复制到新的对象模型

使用这个,因为我必须将我的数据库用户导出到另一个应用程序和旧的,
应用程序正在使用 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

First you need to copy password_salt and encrypted_password to your new object model

Using this because I have to export my database User to another application and old,
app are using devise 1.0.x and new app using 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
若能看破又如何 2024-11-16 18:11:57

如果您要从 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, digest, password, pepper]
    digest = Digest::SHA512.hexdigest('--' << tokens.flatten.join('--') << '--')
  end

  Devise.secure_compare(encrypted_password, digest)
end

请务必替换 stretchespepper 使用您用于加密密码的值。

If you're moving from SHA512, the solution is a bit more involved than moeffju's SHA1 solution:

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, digest, password, pepper]
    digest = Digest::SHA512.hexdigest('--' << tokens.flatten.join('--') << '--')
  end

  Devise.secure_compare(encrypted_password, digest)
end

Be sure to replace stretches and pepper with the values you used to encrypt the passwords.

夜巴黎 2024-11-16 18:11:57

按照 Thomas Dippel 的说明,我制定了更新密码的要点:
https://gist.github.com/1578362

    # 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.
#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 

follow Thomas Dippel instructions i have made a gist that update password:
https://gist.github.com/1578362

    # 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.
#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 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文