如何使用 password_digest 和 Rails 中的表单更新用户密码
How to update user password using password_digest and form in Rails
我有以下文件来更新用户的详细信息。他们目前适用于除密码以外的所有内容。所有逻辑都正常工作,我已经使用 puts
检查是否输入了正确的逻辑部分,但是当调用 @user.update(user_params)
时,密码似乎永远不会在最后更新。
为了让它工作,我必须将下面的两行添加到 UserController 的密码逻辑中,这似乎不合逻辑,因为我进一步调用 @user.update(user_params)
应该使用用户参数更新用户假如。任何意见、建议或意见将不胜感激。
@user.password = params[:user][:password]
@user.save
我没有使用任何 Gems 等进行身份验证,我的用户 table 如下所示
create_table "users", force: :cascade do |t|
t.string "username"
t.string "password_digest"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.string "title"
t.string "firstName"
t.string "surname"
t.index ["username"], name: "index_users_on_username", unique: true
end
用户控制器
class UsersController < ApplicationController
skip_before_action :authorized, only: [:new, :create]
before_action :set_user, only: [:update]
def new
@user = User.new
end
def create
@user = User.create(params.require(:user).permit(:username, :password))
session[:user_id] = @user.id
redirect_to '/welcome'
end
def update
errorMessage = ''
if current_user.username != params[:user][:username]
if User.find_by(username: params[:user][:username]).nil?
else
errorMessage += "Username is already taken"
end
else
end
if !params[:user][:password].blank?
if @user.authenticate(params[:user][:password_confirmation])
else
errorMessage += "Confirmation password is incorrect"
end
else
end
if !errorMessage.blank?
redirect_to account_path, notice: errorMessage
else
@user.update(user_params)
redirect_to account_path
end
end
private
def user_params
params.require(:user).permit(:username, :title, :firstName, :surname,:password, :password_confirmation)
end
def set_user
@user = current_user
end
end
edit.html.erb
<p id=”notice”><%= notice %></p>
<%= form_for current_user do |f|%>
<div class="form-group row col-md-12">
<%= f.label :username, class:"col-sm-2 col-form-label"%><br>
<%= f.text_field :username, class:"form-control col-sm-10" %>
</div>
<div class="form-group row col-md-12">
<div class="col-md-2">
<%= f.label :title%><br>
<%= f.text_field :title, class:"form-control" %>
</div>
<div class="col-md-5">
<%= f.label :firstName, "First Name" %><br>
<%= f.text_field :firstName, class:"form-control" %>
</div>
<div class="col-md-5">
<%= f.label :surname %><br>
<%= f.text_field :surname, class:"form-control" %>
</div>
</div>
<div class="form-group row col-md-12">
<div class="col-md-6">
<%= f.label :password_confirmation, "Current Password"%><br>
<%= f.password_field :password_confirmation, class:"form-control" %>
</div>
<div class="col-md-6">
<%= f.label :password, "New Password"%><br>
<%= f.password_field :password, class:"form-control" %>
</div>
<small id="passwordHelpBlock" class="form-text text-muted col-md-12">
To update your password, please confirm your current password.
</small>
</div>
<%= f.submit "Submit" ,class: "btn btn-primary"%>
<% end %>
用户模型
class User < ApplicationRecord
has_secure_password
end
打开 app/models/user.rb
并将方法 has_secure_password
添加到您的 User
class。 has_secure_password
和 password_digest
在 bcrypt 中一起工作,所以两者都需要存在才能工作。
您的控制器有点复杂,我认为这是导致您出现问题的原因。您应该在视图中输出错误以查看出了什么问题,不幸的是这不是您问题的一部分。
不过,一般来说,有两个选项 可以实现 bcrypt ruby Github repository 中描述的工作。请注意,我没有尝试使用 current_user
、params[:user]
和 @user.authenticate
来消除复杂性并专注于 bcrypt 主题。
选项 1
像这样在用户模型中使用 has_secure_password
:
class User < ApplicationRecord
has_secure_password
end
您需要密码摘要列,并且需要在 user_params 方法中使用 :password
。
def user_params
params.require(:user).permit(:username, :title, :firstName, :surname, :password, :password_confirmation)
end
输入的密码将保存在数据库中的password_digest
列。
选项 2
这在the-user-model part of the bcrypt Github page.
上有描述
在这种情况下,您不使用 has_secure_password
,而是将以下代码添加到您的用户模型中:
class User < ApplicationRecord
include BCrypt
def password
@password ||= Password.new(password_hash)
end
def password=(new_password)
@password = Password.create(new_password)
self.password_hash = @password
end
end
那么你的user_params
方法需要反映:password_hash
属性名:
def user_params
params.require(:user).permit(:username, :title, :firstName, :surname, :password_hash, :password_confirmation)
end
在这种情况下,您的数据库需要 password_hash
列而不是 password_digest
才能使用上面的示例代码使其正常工作。当然,你也可以重新使用password_digest
代替password_hash
,然后将上面代码中的password_hash
替换为password_digest
.
备注
在这两种情况下,我都像您使用 password
字段一样使用视图:
<div class="form-group row col-md-12">
<div class="col-md-6">
<%= f.label :password, "New Password"%><br>
<%= f.password_field :password, class:"form-control" %>
</div>
</div>
我测试中的控制器如下所示:
def update
if @user.update(user_params)
redirect_to @user, notice: 'User was successfully updated.'
else
render :edit
end
end
测试应用程序
我还使用选项 1 和 has_secure_password
添加了这个小测试 rails 应用到 Github 存储库 @ https://github.com/cadamini/rails-bcrypt-ruby-test
我有以下文件来更新用户的详细信息。他们目前适用于除密码以外的所有内容。所有逻辑都正常工作,我已经使用 puts
检查是否输入了正确的逻辑部分,但是当调用 @user.update(user_params)
时,密码似乎永远不会在最后更新。
为了让它工作,我必须将下面的两行添加到 UserController 的密码逻辑中,这似乎不合逻辑,因为我进一步调用 @user.update(user_params)
应该使用用户参数更新用户假如。任何意见、建议或意见将不胜感激。
@user.password = params[:user][:password]
@user.save
我没有使用任何 Gems 等进行身份验证,我的用户 table 如下所示
create_table "users", force: :cascade do |t|
t.string "username"
t.string "password_digest"
t.datetime "created_at", precision: 6, null: false
t.datetime "updated_at", precision: 6, null: false
t.string "title"
t.string "firstName"
t.string "surname"
t.index ["username"], name: "index_users_on_username", unique: true
end
用户控制器
class UsersController < ApplicationController
skip_before_action :authorized, only: [:new, :create]
before_action :set_user, only: [:update]
def new
@user = User.new
end
def create
@user = User.create(params.require(:user).permit(:username, :password))
session[:user_id] = @user.id
redirect_to '/welcome'
end
def update
errorMessage = ''
if current_user.username != params[:user][:username]
if User.find_by(username: params[:user][:username]).nil?
else
errorMessage += "Username is already taken"
end
else
end
if !params[:user][:password].blank?
if @user.authenticate(params[:user][:password_confirmation])
else
errorMessage += "Confirmation password is incorrect"
end
else
end
if !errorMessage.blank?
redirect_to account_path, notice: errorMessage
else
@user.update(user_params)
redirect_to account_path
end
end
private
def user_params
params.require(:user).permit(:username, :title, :firstName, :surname,:password, :password_confirmation)
end
def set_user
@user = current_user
end
end
edit.html.erb
<p id=”notice”><%= notice %></p>
<%= form_for current_user do |f|%>
<div class="form-group row col-md-12">
<%= f.label :username, class:"col-sm-2 col-form-label"%><br>
<%= f.text_field :username, class:"form-control col-sm-10" %>
</div>
<div class="form-group row col-md-12">
<div class="col-md-2">
<%= f.label :title%><br>
<%= f.text_field :title, class:"form-control" %>
</div>
<div class="col-md-5">
<%= f.label :firstName, "First Name" %><br>
<%= f.text_field :firstName, class:"form-control" %>
</div>
<div class="col-md-5">
<%= f.label :surname %><br>
<%= f.text_field :surname, class:"form-control" %>
</div>
</div>
<div class="form-group row col-md-12">
<div class="col-md-6">
<%= f.label :password_confirmation, "Current Password"%><br>
<%= f.password_field :password_confirmation, class:"form-control" %>
</div>
<div class="col-md-6">
<%= f.label :password, "New Password"%><br>
<%= f.password_field :password, class:"form-control" %>
</div>
<small id="passwordHelpBlock" class="form-text text-muted col-md-12">
To update your password, please confirm your current password.
</small>
</div>
<%= f.submit "Submit" ,class: "btn btn-primary"%>
<% end %>
用户模型
class User < ApplicationRecord
has_secure_password
end
打开 app/models/user.rb
并将方法 has_secure_password
添加到您的 User
class。 has_secure_password
和 password_digest
在 bcrypt 中一起工作,所以两者都需要存在才能工作。
您的控制器有点复杂,我认为这是导致您出现问题的原因。您应该在视图中输出错误以查看出了什么问题,不幸的是这不是您问题的一部分。
不过,一般来说,有两个选项 可以实现 bcrypt ruby Github repository 中描述的工作。请注意,我没有尝试使用 current_user
、params[:user]
和 @user.authenticate
来消除复杂性并专注于 bcrypt 主题。
选项 1
像这样在用户模型中使用 has_secure_password
:
class User < ApplicationRecord
has_secure_password
end
您需要密码摘要列,并且需要在 user_params 方法中使用 :password
。
def user_params
params.require(:user).permit(:username, :title, :firstName, :surname, :password, :password_confirmation)
end
输入的密码将保存在数据库中的password_digest
列。
选项 2
这在the-user-model part of the bcrypt Github page.
上有描述在这种情况下,您不使用 has_secure_password
,而是将以下代码添加到您的用户模型中:
class User < ApplicationRecord
include BCrypt
def password
@password ||= Password.new(password_hash)
end
def password=(new_password)
@password = Password.create(new_password)
self.password_hash = @password
end
end
那么你的user_params
方法需要反映:password_hash
属性名:
def user_params
params.require(:user).permit(:username, :title, :firstName, :surname, :password_hash, :password_confirmation)
end
在这种情况下,您的数据库需要 password_hash
列而不是 password_digest
才能使用上面的示例代码使其正常工作。当然,你也可以重新使用password_digest
代替password_hash
,然后将上面代码中的password_hash
替换为password_digest
.
备注
在这两种情况下,我都像您使用 password
字段一样使用视图:
<div class="form-group row col-md-12">
<div class="col-md-6">
<%= f.label :password, "New Password"%><br>
<%= f.password_field :password, class:"form-control" %>
</div>
</div>
我测试中的控制器如下所示:
def update
if @user.update(user_params)
redirect_to @user, notice: 'User was successfully updated.'
else
render :edit
end
end
测试应用程序
我还使用选项 1 和 has_secure_password
添加了这个小测试 rails 应用到 Github 存储库 @ https://github.com/cadamini/rails-bcrypt-ruby-test