【发布时间】:2014-06-08 06:17:01
【问题描述】:
为用户制定密码重置机制。密码长度验证正在触发,我正在尝试了解原因。
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?您如何在没有密码字段的情况下重置他的密码?validation在password field上被调用。所以验证正在触发,因为没有password field。 -
我在密码重置控制器上有一个编辑方法和一个对应的edit.html.erb。我省略了它们,因为验证在它到达之前就被触发了。
-
我添加了它们以尽量减少进一步的混淆。
-
您确定
user给出的password至少是六个字符吗?
标签: ruby-on-rails validation activerecord ruby-on-rails-4