我已经尝试了所有人都在谈论的.authenticate
方法,但是您需要在模型中编写self.authenticate
实现,以便在控制器中使用它,并且它需要BCrypt。很好,但是BCrypt唯一比较密码的方法也都需要加盐,并且该盐不会存储在我的数据库中。我什至不知道如何在需要的地方将其存储在其中,但是SO的某位人士曾经说过,无论如何也没有理由将盐存储在数据库中,所以我宁愿避免使用它。
如何比较给定用户提供的密码与数据库中的密码?
您不必自己实现authenticate
方法。您只需在模型中包括has_secure_password
。
示例:
Gemfile:
gem 'bcrypt' # Is needed for `has_secure_password` to hash the password!
型号:
class User < ActiveRecord::Base
has_secure_password
end
迁移:
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :email
t.string :password_digest # Be sure to have this in your migration or otherwise the `has_secure_password` won't work!
end
add_index :users, :email, unique: true # Good practice to ensure unique email addresses.
end
end
这会自动处理诸如密码散列之类的事情,并增加诸如#authenticate
之类的方法。
验证:
User.find_by(email: params[:user][:email]).authenticate(params[:user][:password]) # This returns the user record if the password is valid or `false` if not
# ----
# Example
class SessionsController < ApplicationController
# ...
def create # Responsible for creating a session
@user = User.find_by(email: params[:user][:email])
if @user.present? && @user.authenticate(params[:user][:password])
# Do login stuff since the password is valid
else
# Don't let the user in.
end
end
end
#authenticate
方法处理所有哈希,依此类推。
我不建议您存储普通密码。这将是一个很大的安全问题,因为如果数据库受到威胁,黑客将拥有用户的所有密码。
您不比较密码,而是将给定密码的商店哈希值与传入的密码(也作哈希处理)进行比较-理想情况下是采用安全机制。
无论如何,我强烈建议您使用现有的解决方案(例如devise,并警告您有关自己实施它。
((很老的问题,现在主要是在提醒我)
如果使用Devise,则可以查询valid_password?
user.valid_password?('wrong password 1') # false
user.valid_password?('valid password 1') # true