Ruby控制台中Rails密码哈希验证正常,重启后失效的原因与解决
Hey there, let's dig into why your login works in the console but fails on the server—this is a super common gotcha with bcrypt!
The Root Cause
Looking at the truncated password digest you shared:
password_digest: $2a$10$AMHXZBl/zXQ9yHOR7uBSiOdsGloArDkxO
A valid bcrypt hash is 60 characters long (like the full one you saw in the console: $2a$10$gKAyDPTNzg.7Xnd7uatzuu0VWZNH6zGPA653RZ.5THB2Rziax1fyC). Your database is storing a shortened version of the hash because the password_digest column's length is too small.
Here's why the console worked temporarily: When you set the password and save, the u object in memory still holds the full valid hash. But once you restart the console or the server reads from the database, it pulls the truncated, invalid hash—hence the InvalidHash error.
Step-by-Step Fix
Check Your Migration
Open the migration where you addedpassword_digest—it probably looks something like this (with a too-short limit):add_column :cms_users, :password_digest, :string, limit: 50The limit is causing the hash to get cut off.
Generate a Migration to Fix the Column Length
Run this in your terminal:rails generate migration ChangePasswordDigestLengthInCmsUsersEdit the New Migration File
Update it to set a sufficiently long limit (70 is safe, leaving room for any future bcrypt format changes):class ChangePasswordDigestLengthInCmsUsers < ActiveRecord::Migration[5.0] def change change_column :cms_users, :password_digest, :string, limit: 70 end endRun the Migration
rails db:migrateReset the User's Password
The old truncated hash is still in the database, so you'll need to re-set the password (do this in the Rails console):u = CmsUser.find_by(username: 'username') u.password = 'password' u.password_confirmation = 'password' u.save!Test the Login
Restart your Rails server, then try logging in again—it should work now!
Quick Verification
To confirm this was the issue, try this in the console after saving the password initially (before resetting):
# After saving, re-fetch the user from the database u = CmsUser.find(1) u.authenticate('password') # This should throw the same InvalidHash error as the server
That's the smoking gun—it proves the database was storing a broken hash.
内容的提问来源于stack exchange,提问作者lastone

