我有一个 Ruby on Rails (4.2.1) 应用程序,它使用 Devise (3.5.1) 对用户进行身份验证,我们正在 Rails (5.0.0) 中重建此应用程序,并且我们正在使用 Devise (4.2.0)。当我将用户表从旧应用程序复制到新应用程序时,就会出现问题,然后在新应用程序中我无法使用旧数据登录。在 devise.rb 初始化程序中,我在两个应用程序中使用相同的 secret_key
,因此不确定为什么我无法使用旧数据登录新应用程序,有什么想法吗?
最佳答案
首先,使用 rails console
确保问题与密码有关,而不是应用程序 - 即,您的用户模型的 valid_password?
调用将失败,并显示正确的密码。
设计使用this默认情况下生成密码哈希的方法:
def self.digest(klass, password)
if klass.pepper.present?
password = "#{password}#{klass.pepper}"
end
::BCrypt::Password.create(password, cost: klass.stretches).to_s
end
它使用 klass.pepper
添加到您的密码(如果存在)。这里的 klass 是你的模型(例如用户),可以是 configured使用胡椒:
Besides :stretches, you can define :pepper, :encryptor, :confirm_within, :remember_for, :timeout_in, :unlock_in among other options.
成本
是新密码存储的盐生成的复杂性,因此应该只影响新哈希值的生成,并且不会影响先前生成的密码的验证。
Devise 使用此方法将输入密码与存储的哈希值进行比较:
def self.compare(klass, hashed_password, password)
return false if hashed_password.blank?
bcrypt = ::BCrypt::Password.new(hashed_password)
if klass.pepper.present?
password = "#{password}#{klass.pepper}"
end
password = ::BCrypt::Engine.hash_secret(password, bcrypt.salt)
Devise.secure_compare(password, hashed_password)
end
只需在两个应用程序版本中对其进行调试即可查看此方法中的哪些输入参数可能不同,例如如果您为模型定义了不同的胡椒,则对于相同的 hashed_value,bcrypt.salt
在两个应用中是不同的。
至于从现有存储的散列密码中获取盐的位置,它实际上是 simple 。存储的字符串简单地由 $
符号分割:
# call-seq:
# split_hash(raw_hash) -> version, cost, salt, hash
#
# Splits +h+ into version, cost, salt, and hash and returns them in that order.
def split_hash(h)
_, v, c, mash = h.split('$')
return v.to_str, c.to_i, h[0, 29].to_str, mash[-31, 31].to_str
end
关于ruby-on-rails - 设计数据库迁移 - Ruby on Rails,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38193606/