将PHP的password_verify转换为Ruby on Rails

时间:2016-08-16 20:11:11

标签: php ruby-on-rails ruby

我们正在将我们的网站从旧的PHP框架转换为Rails,并且非常希望用户能够继续使用旧密码登录。在旧网站上,我们使用password_hash和password_verify来哈希并验证密码。但是,在Rails上,我似乎无法验证旧密码。

以下是我们在PHP中的内容:

哈希:

password_hash($user['salt'] . $password . $user['salt'], PASSWORD_DEFAULT);

验证

password_verify($user['salt'] . $password . $user['salt'], $user['password'])

在新的Rails框架上,我们使用Devise并构建了一个自定义迁移脚本来移动所有内容,并根据存储在db中的password_version识别正确的密码哈希方法,这就是我所做的。在我的用户模型中使用:

def valid_password?(password)
  if password_version == 'legacy'
    hash = BCrypt::Password.new(encrypted_password)
    hash_str = password_salt+password+password_salt

    return hash.is_password? hash_str
  end

  super(password)
end

非常感谢任何想法

1 个答案:

答案 0 :(得分:3)

PHP password_hash密码的格式大致如下:

$2y$10$.vGA1O9wmRjrwAVXD98HNOgsNpDczlqm3Jq7KnEd1rVAGv3Fykk1a

默认的Ruby Bcrypt方法生成以下格式的密码:

$2a$10$GtKs1Kbsig8ULHZzO1h2TetZfhO4Fmlxphp8bVKnUlZCBYYClPohG

对于此处的干净解决方案,您始终可以通过$2y$2a前缀区分这两者。当格式列已经被格式化时,不需要格式列。

例如:

case (encrypted_password[0,3])
when '$2y'
  # Legacy PHP password
  BCrypt::Password.new(encrypted_password.sub(/\A\$2y/, '$2a')).is_password?(salt + password + salt)
when '$2a'
  # Ruby BCrypt password
  BCrypt::Password.new(encrypted_password).is_password?(password) 
else
  # Unexpected type?
end

要成功验证密码,您要做的就是使用Ruby的方法将密码重新写入数据库,逐步替换所有旧的PHP格式的密码。