Rails 使用 bcrypt 的身份验证错误
Rails authentication error using bcrypt
我有一个要在 rails 应用程序 API 上显示的用户列表。我正在使用 bcrypt 来散列密码。我已经在 rails console:
上创建并检查了多个用户的列表
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: "a$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 website.
上给出的代码
这是我的代码:
#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
(在应用程序控制器上,它明确表示用户名和密码)。我认为 rails 可能试图寻找 'password' 但找不到。不过,我对 bcrypt 的了解还不足以说明是这种情况。
其次,在bcrypt website,我没有实现下面的代码,因为我不确定把它放在哪里。这可能是 bcrypt 没有按照我的意愿行事的情况吗?
def login
@user = User.find_by_email(params[:email])
if @user.password == params[:password]
give_token
else
redirect_to home_url
end
end
我不确定缺少什么。
您的数据库架构中有两个密码字段可用
如果您使用 Devise 进行身份验证,则 encrypted_password
字段用于存储密码。
我有一个要在 rails 应用程序 API 上显示的用户列表。我正在使用 bcrypt 来散列密码。我已经在 rails console:
上创建并检查了多个用户的列表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: "a$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 website.
上给出的代码这是我的代码:
#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
(在应用程序控制器上,它明确表示用户名和密码)。我认为 rails 可能试图寻找 'password' 但找不到。不过,我对 bcrypt 的了解还不足以说明是这种情况。
其次,在bcrypt website,我没有实现下面的代码,因为我不确定把它放在哪里。这可能是 bcrypt 没有按照我的意愿行事的情况吗?
def login
@user = User.find_by_email(params[:email])
if @user.password == params[:password]
give_token
else
redirect_to home_url
end
end
我不确定缺少什么。
您的数据库架构中有两个密码字段可用
如果您使用 Devise 进行身份验证,则 encrypted_password
字段用于存储密码。