我有一个包含字段的表:email、password_hash和salt。
在用户注册时,我想验证密码和密码确认,但总是收到can't be blank密码输入错误。
这是我的模型:
attr_accessor :password
validates :password, :presence => true,
:confirmation => true,
:length => { :within => 6..40 }
Run Code Online (Sandbox Code Playgroud)
我来宾我无法验证不是数据库的字段,但是如何对用户输入的密码进行验证?
我在数据库中没有密码字段,因为我加密了password获得的输入,然后将其存储在数据库password_hash字段中。
编辑 :
这是数据库表:
class CreateStudents < ActiveRecord::Migration
def change
create_table :students do |t|
t.string :first_name
t.string :last_name
t.string :email
t.string :password_hash
t.string :salt
t.boolean :activated
t.timestamps
end
end
end
Run Code Online (Sandbox Code Playgroud)
这是注册的视图:
<%= form_for @student, url: {action: 'create'} do |form| %>
<p style="font-size:smaller; color:red">
<% @student.errors.messages.each do |att, msg| %>
<%= msg[0] %><br>
<% end %>
<p>
<%= form.label :first_name %><br>
<%= form.text_field :first_name %>
<p>
<%= form.label :last_name %><br>
<%= form.text_field :last_name %>
<p>
<%= form.label :email %><br>
<%= form.text_field :email %>
<p>
<%= form.label :password %><br>
<%= form.password_field :password %>
<p>
<%= form.label :password_confirmation %><br>
<%= form.password_field :password_confirmation %>
<p>
<%= form.submit %>
<% end %>
Run Code Online (Sandbox Code Playgroud)
这是控制器:
def sing_up
@student = Student.new
render 'sing_up'
end
def create
@student = Student.new
@student.first_name = params[:student][:first_name]
@student.last_name = params[:student][:last_name]
@student.email = params[:student][:email]
@student.salt = BCrypt::Engine.generate_salt
@student.password_hash = BCrypt::Engine.hash_secret(params[:student][:password], @student.salt)
if @student.save
redirect_to controller: 'singups', action: 'index'
else
render 'sing_up'
end
end
Run Code Online (Sandbox Code Playgroud)
最后,这是模型
class Student < ActiveRecord::Base
attr_accessor :password
validates :first_name, :length => { minimum: 3, message: "first_name" }
validates :last_name, :length => { minimum: 3, message: "last_name" }
validates :email, :presence => { message: 'email' },
:format => { with: /\A[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]+\z/ , message: 'email format' },
:uniqueness => { message: 'uniqueness?' }
validates :password, :confirmation => { message: 'password' },
:length => { minimum: 6, message: 'password length' }
end
Run Code Online (Sandbox Code Playgroud)
每次用户输入密码时,:confirmation => { message: 'password' }无论密码是什么,第一次验证都会失败。
如果我删除validates :password部分,一切正常,但用户输入的密码未经过验证。
您正在验证用户的password属性,但您从未首先为其分配值。至少,您需要将其添加到控制器代码中:
@student.password = params[:student][:password]
@student.password_confirmation = params[:student][:password_confirmation]
Run Code Online (Sandbox Code Playgroud)
然而,更简洁的方法是使用批量分配 - 去掉所有 @student.xxx = yyy 并将其替换为:
@student = Studen.new(params[:student])
Run Code Online (Sandbox Code Playgroud)
然后,将密码哈希方法移至模型中,并在每次保存之前自动触发(如果存在密码属性):
class User < ActiveRecord::Base
# ...
before_save :hash_password, :if => proc{ |u| !u.password.blank? }
# ....
protected
def hash_password
self.salt = BCrypt::Engine.generate_salt
self.password_hash = BCrypt::Engine.hash_secret(password, salt)
end
end
Run Code Online (Sandbox Code Playgroud)
这样你就不必在控制器中执行任何操作,但:
def create
@student = Student.new(params[:student])
if @student.save
redirect_to controller: 'singups', action: 'index'
else
render 'sing_up'
end
end
Run Code Online (Sandbox Code Playgroud)
并在您的模型中拥有它所属的所有其他逻辑。
编辑:为了使批量分配能够与最新版本的 Rails 3 一起使用,您需要将要分配的属性设置为这样attr_accessible,如下所示:
class Student < ActiveRecord::Base
# ...
attr_accessible :first_name, :last_name, :email, :password # but NOT the hash or salt!!
end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5934 次 |
| 最近记录: |