为用户使用密码重置机制。密码长度验证触发,我试图理解为什么。密码验证触发何时不应触发?
user.rb
class User < ActiveRecord::Base
has_secure_password
validates :password, length: { minimum: 6 }
...
def create_password_reset_token
self.update_attributes!(password_reset_token: SecureRandom.urlsafe_base64, password_reset_sent_at: Time.zone.now)
end
def reset_password(params)
self.update_attributes!(params)
self.update_attributes!(password_reset_token: nil, password_reset_sent_at: nil)
end
end
password_resets_controller.rb
def create
user = User.find_by_email(params[:email])
if user
user.create_password_reset_token
UserMailer.password_reset_email(user).deliver
redirect_to root_url, :notice => "Email sent with password reset instructions!"
else
flash[:error] = "A user with that email address could not be found."
render 'new'
end
end
def edit
@user = User.find_by_password_reset_token(params[:id])
if @user
render 'edit'
else
flash[:error] = "Invalid password reset code."
redirect_to root_url
end
end
def update
@user = User.find_by_password_reset_token(params[:id])
if @user.password_reset_sent_at < 2.hours.ago
flash[:error] = "Password reset has expired."
redirect_to new_password_reset_path
elsif @user.reset_password(user_params)
flash[:success] = "Password has been reset."
redirect_to root_url
else
render 'edit'
end
end
password_resets/new.html.erb:
<%= form_tag password_resets_path, :method => :post do %>
<%= label_tag :email %>
<%= text_field_tag :email, params[:email] %>
<%= submit_tag "Reset Password" %>
<% end %>
个password_resets/edit.html.erb:
<%= form_for @user, :url => password_reset_path(params[:id]) do |f| %>
<h1 class="centertext">Reset Password</h1>
<%= render 'shared/error_messages', object: f.object %>
<%= f.label :password %>
<%= f.password_field :password %>
<%= f.label :password_confirmation, "Confirm password" %>
<%= f.password_field :password_confirmation %>
<%= f.submit "Update password" %>
<% end %>
错误是:
Validation failed: Password is too short (minimum is 6 characters)
抛出它是create_password_reset_token
方法内的行:
self.update_attributes!(password_reset_token: SecureRandom.urlsafe_base64, password_reset_sent_at: Time.zone.now)
为什么在验证触发在这里?我没有对密码本身做任何事情。我只是在用户记录中创建一个令牌和一段时间。
将验证更改为说on: :create
使其不触发。问题是用户可以将密码重置为少于六个字符。
澄清
需要明确的是,操作顺序是:“我忘记了密码”
- 用户点击一个链接说
- 它们被带到password_reset_controller/new.html.erb。此表格有一个字段:电子邮件地址。他们输入他们的电子邮件并提交。
- 控制器会检查该用户是否存在。如果有,它会告诉模型生成一个password_reset_token。
- 控制器然后命令一个电子邮件发送给包含令牌的URL的用户。
- 用户单击URL。如果令牌有效,它们将被带到edit.html.erb并且他们输入他们的新电子邮件和它的确认。
- 控制器调用reset_password方法,该方法实际上会重置用户的密码。
当前,在步骤2中,验证触发后,他们进入他们的电子邮件,然后单击提交。
为什么你的'new.html.erb'没有'password field'?如何在没有密码字段的情况下重置密码? “验证”在“密码字段”上被调用。所以验证是触发的,因为没有“密码字段”。 – Pavan
我对密码重置控制器和相应的edit.html.erb有一个编辑方法。我省略了它们,因为验证在它到达之前就被触发了。 –
我添加了它们以最大限度地减少混淆。 –