在我的Rails 4.0.9应用程序中,使用BCrypt 3.1.7和Clearance 1.4.2进行身份验证,我在更新用户信息时收到错误。尽管没有输入新密码或密码确认,我收到错误“密码不能为空。”
我在搜索引擎优化和谷歌搜索方面看起来很高,而且找不到任何解决方案。大部分都是针对早期版本的Rails,现在可能已经过时了,而其他版本并不适合我的确切情况(可能是因为我只是做了一些愚蠢的事情)。
我可以从编辑表单中删除密码和password_confirmation字段,但我做希望用户能够更新他们的密码,同时还要更新他们的姓名或电子邮件地址,如果他们有这么倾向的话。
'has_secure_password'应该只在create上验证,但似乎也在更新时验证。为了解决这个问题,我已经禁用了我的用户模型对password和password_confirmation的验证,只需要使用'has_secure_password'来验证这些参数。你能明白为什么我收到验证错误吗?清除宝石是否会覆盖has_secure_passwords的默认行为,或以任何方式影响验证?
用户模型
class User < ActiveRecord::Base
include Clearance::User
belongs_to :studio
has_one :public_user
before_save { self.email = email.downcase }
before_create :create_remember_token
after_create :make_public_user
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i
validates :email, presence: true,
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
# validates :password, length: { minimum: 6, on: :create }
# validates :password_confirmation, presence: { on: :create }
...
用户控制器
...
def edit
end
def update
if @user.update_attributes(user_params)
flash[:success] = "Profile updated"
redirect_to @user
else
render 'edit'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation, :password_digest)
end
...
编辑表单(实际上是“_fields.html.erb”部分)
<%= render 'shared/error_messages', object: f.object %>
<div class="control-group">
<%= f.label :name, class: "control-label" %>
<div class="controls">
<%= f.text_field :name %>
</div>
</div>
<div class="control-group">
<%= f.label :email, class: "control-label" %>
<div class="controls">
<%= f.text_field :email %>
</div>
</div>
<div class="control-group">
<%= f.label :password, class: "control-label" %>
<div class="controls">
<%= f.password_field :password, placeholder: 'Enter new password if changing' %>
</div>
</div>
<div class="control-group">
<%= f.label :password_confirmation, "Confirmation", class: "control-label" %>
<div class="controls">
<%= f.password_field :password_confirmation, placeholder: 'Confirm your new password if changing' %>
</div>
</div>
传递给控制器的参数
Parameters: {"utf8"=>"✓", "authenticity_token"=>"[FILTERED]", "user"=>{"name"=>"Ransom Kshlerin III", "email"=>"example-1@samplestudio.com", "password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]"}, "commit"=>"Save changes", "id"=>"4"}
修改
当我禁用'has_secure_password'时,我仍然会收到验证错误,这让我相信Clearance的验证会返回错误。我想我需要覆盖Clearance的密码验证,但仅限于更新用户时。我应该怎么做呢?
编辑2:
我将采取完全不同的方法。我不会直接在此表单上重置密码,而是提供重置密码的链接,该链接会向用户发送一封电子邮件,其中包含重置密码的链接。
答案 0 :(得分:2)
传递给控制器的参数中有"password"=>"", "password_confirmation"=>""
出现(不要担心[FILTERED]
,这只意味着Rails不会将参数打印到日志)。
致电params.require(:user).permit(:password, :password_confirmation)
包括{ password: "", password_confirmation: "", # plus the other keys }
时。
将此哈希传递给@user.update_attributes({password: '', password_confirmation: ''})
时,密码的状态验证将启动,并防止设置空密码。
不尝试设置空密码的一个选项可能是从user_params
哈希中删除密钥,除非它们的值被认为存在。
def user_params
user_params = params.require(:user).permit(:name, :email, :password, :password_confirmation) # don't permit `password_digest` here, that database column should not be allowed to be set by the user!
# Remove the password and password confirmation keys for empty values
user_params.delete(:password) unless user_params[:password].present?
user_params.delete(:password_confirmation) unless user_params[:password_confirmation].present?
user_params
end
答案 1 :(得分:0)
has_secure_password
和Clearance gem每个都验证密码和密码确认,而且我还不够熟练,无法超越Clearance的验证(在我脑海中)。所以我采取了不同的方法。密码和密码确认不会包含在此编辑表单中。
我不会直接在此表单上重置密码,而是提供重置密码的链接,该链接会向用户发送一封电子邮件,其中包含重置密码的链接。我想这里的额外好处是,如果用户设法以其他用户身份登录,他们将无法重置该用户的密码,除非他们还侵入了其他用户&# 39;电子邮件帐户。
答案 2 :(得分:-1)
Clearance提供了一条明确的(^_^)路径来规避密码要求:
# Always false. Override this method in your user model to allow for other
# forms of user authentication (username, Facebook, etc).
#
# @return [false]
def password_optional?
false
end
例如,在您的用户模型中,您可以执行以下操作:
# app/models/user.rb
class User < ApplicationRecord
include Clearance::User
def password_optional?
true
end
end