哈希密码未保存在密码列中

Hash password not saved in the password column

我试图在注册时将哈希密码存储在我的 users table 中。请看我的代码:

users_controller.rb

def login
  @title = 'Login'
  #render layout: 'login'
end
def create_login
  user = User.authenticate(params[:user][:username], params[:user][:password])
  if user
    log_in user
    redirect_to '/admin'
  else
    flash[:danger] = 'Invalid email/password combination' # Not quite right!
    redirect_to :back
  end
end
def register
    @user = User.new
    @title = 'Register'
  end

  def create_register
    params[:user][:uniq_id] = generate_uniq
    @user = User.new(create_user_params)
    #raise @user.inspect
    respond_to do |format|
      if @user.save
        format.html { redirect_to :success, success: 'Registration was successfully created.' }
        format.json { redirect_to :register, status: :created, location: @users }
      else
        format.html { render :register }
        format.json { render json: @users.errors, status: :unprocessable_entity }
      end
    end
  end

private

def create_user_params
    params.require(:user).permit(:uniq_id, :name, :username, :email, :password, :password_confirmation, :password_salt, :dob, :address)
  end

register.html.erb

<%= form_tag("/register", method: "post") do %>
        <%#= form_tag(@user) do |f| %>
         <% if @user.errors.any? %>
          <div id="error_explanation">
            <h2><%= pluralize(@user.errors.count, "error") %> prohibited this user from being saved:</h2>
            <ul>
              <% @user.errors.full_messages.each do |message| %>
                <li><%= message %></li>
              <% end %>
            </ul>
          </div>
        <% end %>


          <%= text_field :user, :name, placeholder:'NAME', required: true %>
          <div style="position: relative;">
            <span id="chk-username" style="position: absolute;font-size: 12px;right: 2%; bottom: 5%; z-index: 9; display: block;"></span>
            <%= text_field :user, :username, placeholder:'USERNAME', 'data-validate':"/users/check_username", required: true %>
          </div>
          <div style="position: relative;">
            <span id="chk-email" style="position: absolute;font-size: 12px;right: 2%; bottom: 5%; z-index: 9; display: block;"></span>
            <%= text_field :user, :email, placeholder:'EMAIL', 'data-validate':"/users/check_email", required: true %>
          </div>
          <%= password_field :user, :password, placeholder:'PASSWORD', required: true %>  
          <%= password_field :user, :password_confirmation, placeholder:'CONFIRM PASSWORD', required: true %> 
          <div class="submit">
            <input type="submit" value="REGISTER" >
            <input type="button" onclick="location.href = '<%= request.base_url %>/login'" value="LOGIN" >
          </div>    
          <p><a href="#">Forgot Password ?</a></p>
<% end %>

user.rb

class User < ActiveRecord::Base
  #has_secure_password

  attr_accessor :password
  before_save :encrypt_password

  validates :name, presence: true


  validates :name, length: { minumum:2, maximum: 30 }

  validates :password, :presence =>true,
    :length => { :minimum => 6, :maximum => 40 },
    :confirmation =>true

  validates :username, :presence => true,
    :uniqueness => { :case_sensitive => false }

  email_regex = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, :presence => true,
    :format => { :with => email_regex },
    :uniqueness => { :case_sensitive => false }


  def self.authenticate(input_username, input_password)
    user = find_by_username(input_username)
    if user && user.password == BCrypt::Engine.hash_secret(input_password, user.password_salt)
      user
    else
      nil
    end
  end

  def encrypt_password
    if password.present?
      self.password_salt = BCrypt::Engine.generate_salt
      self.password = BCrypt::Engine.hash_secret(password, password_salt)
    end
  end
end

routes.rb

get    'register'   => 'users#register'
post   'register'   => 'users#create_register'

这是我的数据库 table。

users.sql(自定义table)

+----+----------+------------+-----------+----------------+
| id | name     | username   |  password |  password_salt |
+----+----------+------------+-----------+----------------+
|  1 | chinmay  | chinu      | NULL      |afWDt.. |
|  2 | sanjib   | sanjib     | NULL      |aDyMr.. |
+----+----------+------------+-----------+----------------+

我在 password 列中得到 NULL 值。请帮助我,让我知道我的代码中的错误所在。

你的主要错误是你正在使用 attr_accessor :password 为密码属性创建一个 getter/setter 覆盖 ActiveRecord 从数据库创建的 getter 和 setter架构。

然而,您的整个密码加密方法存在缺陷 - 您应该将 password 作为纯粹的 virtual attribute 并将您的数据库列命名为 password_digestencrypted_password.

除非出于纯粹的学习目的,否则应该使用 Rails 提供的 has_secure_password 宏,而不是重新发明密码加密轮并被黑客攻击。

1。向用户添加 password_digest 列:

rails g migration AddPassWordDigestToUser password_digest:string:index

您可能想要删除 password_salt 列,因为它未被 ActiveModel::SecurePassword 使用。

class AddPassWordDigestToUser < ActiveRecord::Migration
  def change
    add_column :users, :password_digest, :string
    add_index :users, :password_digest
    remove_column :users, :password_salt
    remove_column :users, :password
  end
end

2。将 has_secure_password 添加到用户模型:

class User < ActiveRecord::Base
  has_secure_password
end

3。 RESTful 路线

您可能想要更正您的路线,使它们以资源为导向而不是以行动为导向,并遵循 rails 约定:

GET  /registrations/new   registations#new     - sign up form
POST /registrations       registations#create  - create user

GET  /sessions/new        sessions#new         - sign in form
POST /sessions            sessions#create      - sign in user

您可以设置路线:

resources :registrations, only: [:new, :create]
resources :sessions, only: [:new, :create]

参见 Rails Routing from the Outside In

4。绑定表单和控制器。

您正在正确设置控制器,但是您的表单未绑定到您在控制器中创建的 @user 模型实例。

这意味着用户输入的值在表单提交失败后消失。

还要注意变量的复数化和命名!您不一致地使用 @user@users。在这种情况下 @users 将始终为 nil 并导致错误。

app/controllers/registrations_controller.rb:

class RegistationsController < ApplicationController

  def new
    @user = User.new
  end

  def create
    # Use a block instead of messing with the incoming params.
    @user = User.new(user_params) do |u|
      u.uniq_id = generate_uniq
    end 

    if @user.save
      respond_to do |format|
        format.html { redirect_to root_path, success: "Welcome #{@user.email}" }
        format.json { status: :created, location: @user } 
      end
    else
      respond_to do |format|
        format.html { redirect_to :new }
        format.json { render json: @user.errors, status: :unprocessable_entity } 
      end
    end
  end

  private

    def user_params
      params.require(:user).permit(:email, :password, :password_confirmation)
    end

end

app/views/registrations/new.html.erb:

<%= form_for(@user, url: registrations_path) do |f| %>
  <div class="row">
    <%= f.label :email %>
    <%= f.text_field :email %>
  </div>
  <div class="row">
    <%= f.label :password %>
    <%= f.password_field :password %>
  </div>
  <div class="row">
    <%= f.label :password_confirmation %>
    <%= f.password_field :password_confirmation %>
  </div>
<% end %>