如何解决将现有的密码哈希转换为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 举报,一经查实,本站将立刻删除。