Ошибка аутентификации Rails с использованием bcrypt

У меня есть список пользователей, которых я хочу показать в приложении rails API. Я использую bcrypt для хеширования пароля. Я создал и проверил, что у меня есть список нескольких пользователей на консоли rails:

2.2.2 :010 > User.all
  User Load (8.9ms)  SELECT "users".* FROM "users"
 => #<ActiveRecord::Relation [#<User id: 2, created_at: "2016-07-19 06:23:35", updated_at: "2016-07-19 06:23:35", username: "iggy1", encrypted_password: "", reset_password_token: nil, reset_password_sent_at: nil, remember_created_at: nil, sign_in_count: 0, current_sign_in_at: nil, last_sign_in_at: nil, current_sign_in_ip: nil, last_sign_in_ip: nil, password_digest: "$2a$10$We2V5sFx3XJNHP9iHTx.5udLA9hEbJVDOcA01nemj0R...">,

Я тестирую это на локальном хосте. Цель для меня, чтобы пойти в http://localhost:3000/api/users и иметь список всех пользователей в формате JSON.

Когда я захожу на сайт, мне подсказывают имя пользователя и пароль. Я ввел одно из имени пользователя и пароля пользователя: "iggy1", "helloworld". Я вижу это сообщение об ошибке:

SQLite3::SQLException: no such column: users.password: SELECT "users".* FROM "users" WHERE "users"."username" = ? AND "users"."password" = 'helloworld'

Моя схема выглядит так:

create_table "users", force: :cascade do |t|
    t.datetime "created_at",                          null: false
    t.datetime "updated_at",                          null: false
    t.string   "username"
    t.string   "encrypted_password",     default: "", null: false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          default: 0,  null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
    t.string   "password_digest"
  end

Я попытался немного поиграть с этим. Я следовал коду, указанному на сайте bcrypt.

Вот мои коды:

#controller/api/users_controller.rb

class UsersController < ApplicationController
  def create
    @user = User.new(params[:user])
    @user.password = params[:password]
    @user.save!
  end
end


#controllers/users_controller.rb

class UsersController < ApplicationController
  def create
    @user = User.new(params[:user])
    @user.password = params[:password]
    @user.save!
  end
end


#models/user.rb

require 'bcrypt'

class User < ActiveRecord::Base
  #include 'bcrypt'
  has_many :lists
  has_many :items, through: :lists
  has_secure_password

  def password
    @password ||= Password.new(password_hash)
  end

  def password=(new_password)
    @password = Password.create(new_password)
    self.password_hash = @password
  end

end


#controllers/application_controller.rb

class ApiController < ApplicationController
  skip_before_action :verify_authenticity_token
  private

def authenticated?
    authenticate_or_request_with_http_basic {|username, password| User.where( username: username, password: password).present? }
  end
end

#config routes

Rails.application.routes.draw do
  namespace :api, defaults: { format: :json} do #supports JSON requests
    resources :users
  end
end

Теперь, когда я включил строку "bcrypt" без комментариев, я вижу другую ошибку, когда я иду в http://localhost:3000/api/users

wrong argument type String (expected Module)

У меня есть несколько гипотез о том, почему это происходит.

Во-первых, я думаю, что это потому, что я использую bcrypt, и у него есть password_digest. У меня нет конкретно password на моей схеме (на контроллере приложения явно указаны имя пользователя и пароль). Я думаю, что рельсы, возможно, пытались найти "пароль", но не смогли его найти. Я не знаю bcrypt достаточно, чтобы сказать, что это так.

Во-вторых, на веб-сайте bcrypt я не реализовал следующий код, потому что не знал, где его разместить. Может быть, дело в том, что bcrypt ведет себя не так, как я хотел?

  def login
    @user = User.find_by_email(params[:email])
    if @user.password == params[:password]
      give_token
    else
      redirect_to home_url
    end
  end

Я не был уверен, чего не хватает.

1 ответ

Решение

В вашей схеме БД доступны два поля для пароля

Если вы используете Devise для аутентификации, то encrypted_password поле используется для хранения пароля.

Другие вопросы по тегам