You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails 7集成Devise注册时encrypted_password未保存密码问题

问题环境

在Rails 7.0.3 + PostgreSQL环境下使用Devise 4.8.1搭建用户认证功能,前期操作如下:

  • 执行rails g devise:views生成Devise配套视图文件
  • 执行rails db:migrate完成数据库迁移操作
现有代码

User模型代码

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :confirmable
  has_many :posts, foreign_key: 'author_id'
  has_many :comments, foreign_key: 'author_id'
  has_many :likes, foreign_key: 'author_id'

  attr_accessor :password, :password_confirmation

  validates :name, presence: true
  validates :PostsCounter, presence: true, numericality: { greater_than_or_equal_to: 0 }

  def recent_posts
    posts.order(created_at: :desc).limit(3)
  end
end

Devise相关数据库迁移代码

# frozen_string_literal: true

class AddDeviseToUsers < ActiveRecord::Migration[7.0]
  def self.up
    change_table :users do |t|
      ## Database authenticatable
      t.string :email,              null: false, default: ""
      t.string :encrypted_password, null: false, default: ""

      ## Recoverable
      t.string   :reset_password_token
      t.datetime :reset_password_sent_at

      ## Rememberable
      t.datetime :remember_created_at

      ## Trackable
      # 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

      ## Confirmable
      t.string   :confirmation_token
      t.datetime :confirmed_at
      t.datetime :confirmation_sent_at
      t.string   :unconfirmed_email # Only if using reconfirmable

      ## Lockable
      # t.integer  :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts
      # t.string   :unlock_token # Only if unlock strategy is :email or :both
      # t.datetime :locked_at


      # Uncomment below if timestamps were not included in your original model.
      # t.timestamps null: false
    end

    add_index :users, :email,                unique: true
    add_index :users, :reset_password_token, unique: true
    add_index :users, :confirmation_token,   unique: true
    # add_index :users, :unlock_token,         unique: true
  end

  def self.down
    # By default, we don't want to make any assumption about how to roll back a migration when your
    # model already existed. Please edit below which fields you would like to remove in this migration.
    raise ActiveRecord::IrreversibleMigration
  end
end
问题描述

此前Devise功能运行正常,用户注册时密码会自动加密后存入数据库,目前出现异常:

  • 用户完成注册后尝试登录时,系统提示邮箱或密码无效
  • 核查PostgreSQL数据库发现,encrypted_password字段未存入任何值
  • 已尝试在线检索解决方案、重装相关gem,均未修复问题,暂不清楚问题成因
  • 完整问题代码存放在项目feature/devise分支,排查需要更多代码信息可随时补充。
问题原因

核心问题是User模型中手动添加的attr_accessor :password, :password_confirmation覆盖了Devise原生逻辑。
Devise的database_authenticatable模块已经内置了这两个属性的处理逻辑:给password字段赋值时,模块会自动对明文密码做BCrypt哈希加密,将加密结果写入encrypted_password字段并持久化到数据库。手动定义的attr_accessor会把Devise的原生属性方法覆盖,导致密码赋值仅存储在普通Ruby实例变量中,完全不会触发加密写库流程,最终数据库里encrypted_password为空,登录校验自然无法通过。

修复方案

直接删除User模型里的attr_accessor :password, :password_confirmation这行代码,重启Rails服务后重新注册账号测试即可,加密后的密码会正常写入数据库,登录功能恢复正常。


内容的提问来源于stack exchange,提问作者Mirou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 21:06:21