使用BCrypt哈希Ruby on Rails密码无法保存至PostgreSQL用户表
问题:bcrypt-ruby哈希密码无法保存到PostgreSQL的users表
我尝试使用bcrypt-ruby对密码进行哈希处理并保存到PostgreSQL的users表中,但无法成功保存哈希值。以下是我的操作步骤:
用户模型(User Model)
require 'bcrypt' class User < ApplicationRecord include ActiveModel::SecurePassword include BCrypt has_secure_password attr_accessor :password attr_accessor :password_digest enum :user_type, { :registered => 1, :administrator => 2 } validates :email, presence: true validates_format_of :email, with: URI::MailTo::EMAIL_REGEXP validates :password_digest, presence: true validates :password_confirmation, presence: true end
Rails迁移文件(Rails Migration)
class User < ActiveRecord::Migration[7.0] create_table :users do |t| t.string :username, null: false, default: "" t.string :email, null: false, default: "" t.string :password_digest, null: false, default: "" t.string :user_type, default: 'registered' t.timestamps null: false end add_index :users, :username, unique: true add_index :users, :email, unique: true add_index :users, :user_type end
Rails控制台操作(Rails Console)
include BCrypt @user = User.new @user.username = "test123456" @user.email="test123456@gmail.com" @user.user_type = 1 @user.password = "test123456" @user.password_digest = Password.create("test123456") @user.password_confirmation = "test123456" @user.save!
Rails控制台生成的SQL
TRANSACTION (0.2ms) BEGIN User Create (0.4ms) INSERT INTO "users" ("username", "email", "password_digest", "user_type", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id" [["username", "test123456"], ["email", "test123456@gmail.com"], ["password_digest", "[FILTERED]"], ["user_type", "1"], ["created_at", "2024-10-03 13:53:37.193227"], ["updated_at", "2024-10-03 13:53:37.193227"]] TRANSACTION (0.8ms) COMMIT
PostgreSQL数据库情况
附截图显示密码哈希未正确保存
解决方案
你的代码存在几个核心问题,导致密码哈希无法正确持久化:
1. 错误覆盖了password_digest的存取方法
ActiveRecord会自动为数据库表字段生成对应的getter/setter方法,手动添加attr_accessor :password_digest会覆盖这些原生方法,导致哈希值无法写入数据库。
2. 冗余引入密码相关模块
has_secure_password已经内置了ActiveModel::SecurePassword的功能,并且自动集成了bcrypt,不需要额外require 'bcrypt'或include BCrypt。
3. 控制台操作冗余
设置has_secure_password后,只需提供password和password_confirmation,Rails会自动生成并保存password_digest,无需手动赋值。
修正后的用户模型
class User < ApplicationRecord has_secure_password enum :user_type, { registered: 1, administrator: 2 } validates :email, presence: true, format: { with: URI::MailTo::EMAIL_REGEXP } validates :password, presence: true, confirmation: true validates :username, presence: true, uniqueness: true end
修正后的控制台操作
@user = User.new( username: "test123456", email: "test123456@gmail.com", user_type: :registered, password: "test123456", password_confirmation: "test123456" ) @user.save!
额外迁移文件修正
原迁移中user_type定义为字符串类型,但enum使用整数映射,建议改为整数类型避免类型不匹配,同时修正迁移文件名(需遵循[action]_table_name规范):
class CreateUsers < ActiveRecord::Migration[7.0] def change create_table :users do |t| t.string :username, null: false, default: "" t.string :email, null: false, default: "" t.string :password_digest, null: false, default: "" t.integer :user_type, default: 1 t.timestamps null: false end add_index :users, :username, unique: true add_index :users, :email, unique: true add_index :users, :user_type end end
执行修正后的代码后,通过User.last.password_digest可以验证是否生成了以$2a$开头的bcrypt哈希值。
内容的提问来源于stack exchange,提问作者user1645914
相关产品推荐
相关产品推荐

