【问题标题】:How to update user password using password_digest and form in Rails如何在 Rails 中使用 password_digest 和 form 更新用户密码
【发布时间】:2023-04-05 15:01:01
【问题描述】:

我有以下文件来更新用户详细信息。它们目前适用于除密码之外的所有内容。所有逻辑都正常工作,我使用puts 来检查是否输入了正确的逻辑部分,但是当调用@user.update(user_params) 时,密码似乎永远不会在最后更新。

为了让它工作,我必须将下面的 2 行添加到 UserController 中的密码逻辑中,这似乎不合逻辑,因为我进一步调用 @user.update(user_params) 应该使用提供的用户参数更新用户。任何意见、建议或 cmets 将不胜感激。

@user.password = params[:user][:password]
@user.save

我没有使用任何 Gems 等进行身份验证,我的用户表如下所示

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

【问题讨论】:

  • 您可以添加您的User 型号代码吗?
  • 我已经添加了这个
  • 似乎直截了当:medium.com/@ashleymcolletti/…
  • 附加的帖子只显示了您如何创建用户,我已经可以做到了。我希望能够更改现有用户的密码。

标签: ruby-on-rails bcrypt ruby-on-rails-6


【解决方案1】:

您的控制器有点复杂,我认为这会以某种方式导致您的问题。您应该在视图中输出错误以查看出了什么问题,不幸的是,这不是您的问题的一部分。

不过,一般而言,有 两种选择 可以实现 bcrypt ruby Github repository 中描述的这项工作。请注意,我没有尝试使用 current_userparams[: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

【讨论】:

  • 关于选项 1,我已经这样做了,如附件代码所示
  • 那么你需要告诉我们你得到的错误信息。它可能会在另一个地方静默失败,例如验证。
  • 我没有收到错误消息,如果我将控制器更改为与您在上面放置的相同,那么它适用于除密码以外的所有其他字段
  • 我已经用两件事更新了测试仓库 - 当前密码检查和用户确认新密码的需要。在github.com/cadamini/rails-bcrypt-ruby-test 再次查看。为此,我使用了stackoverflow.com/a/15829023/3842598 中建议的方法 - 也许这是您查找密码摘要问题的起点。
  • 谢谢,帮了大忙 :)
【解决方案2】:

打开 app/models/user.rb 并将方法 has_secure_password 添加到您的 User 类中。 has_secure_passwordpassword_digest 在 bcrypt 中一起工作,因此两者都需要在场才能正常工作。

【讨论】:

  • 我的代码中已经有了这个。我已编辑问题以包含用户模型
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-12
  • 2016-08-22
相关资源
最近更新 更多