我不知道为什么会发生这种情况,但 Rails 正在将字符串作为 BLOB 保存到 SQLite。在我的应用程序中创建新用户之前,我会先获取他们的纯字符串密码并对其进行 MD5,然后再保存到数据库:
class User < ActiveRecord::Base
before_create :encrypt_password
def encrypt_password
self.password = Digest::MD5.hexdigest(self.password)
end
end
但是,密码字段每次都会作为一个奇怪的 BLOB 进入 SQLite!我能说的唯一方法是将表导出到 SQL 时,我可以看到该字段的真实性质:
INSERT INTO "users" VALUES (24, '[email protected]', X'3639366432396530393430613439353737343866653366633965666432326133');
我勒个去??因此,现在当我尝试通过查找用户的电子邮件和 MD5 哈希密码来验证用户身份时,每次都会失败。 REAL 字符串显然与 BLOB 不匹配:
User.find_by_email_and_password('joh[email protected]', Digest::MD5.hexdigest('password') => nil
我一生中从未使用过 BLOB,更不用说作为用户表的密码字段了。我的迁移明确定义了:string
作为数据类型。做一个User.columns
清楚地表明:
#<ActiveRecord::ConnectionAdapters::SQLiteColumn:0x00000105256ce0 @name="password", @sql_type="varchar(255)"
我已经在这个应用程序上工作了一个月的大部分时间,直到昨晚我为用户模型编写一些测试时才发现这个问题。尝试对用户进行身份验证的测试每次都会失败,因此我开始在控制台中手动构建用户,并发现密码永远不会匹配,因此所有用户查找都会失败。
用于创建用户的 Rails 调试信息如下所示:
INSERT INTO "users" ("created_at", "email", "first_name", "last_login_at", "last_name", "login_count", "password", "role_id", "twitter", "updated_at", "uuid") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) [["created_at", Mon, 04 Jul 2011 18:50:58 UTC +00:00], ["email", "[email protected]"], ["first_name", "Ebba"], ["last_login_at", nil], ["last_name", "Bayer"], ["login_count", nil], ["password", "5f4dcc3b5aa765d61d8327deb882cf99"], ["role_id", 2], ["twitter", nil], ["updated_at", Mon, 04 Jul 2011 18:50:58 UTC +00:00], ["uuid", "7ab57110-889c-012e-e207-482a140835c4"]]
当我转换为常规 SQL 时,它工作得很好,所以一定有其他事情发生在某个地方。到底是怎么回事?!?!
- sqlite3 3.6.12
- 导轨 3.1.0.rc4
- sqlite3-ruby 1.3.3
UPDATE
它变得越来越陌生......如果我在我的代码中硬编码一些随机字符串encrypt_password
方法然后它正确地进入数据库:
def encrypt_password
self.password = 'foo'
end
我什至可以将其硬编码为字符串“password”的实际 MD5 哈希值,并且它可以工作:
def encrypt_password
self.password = '5f4dcc3b5aa765d61d8327deb882cf99'
end
但如果我告诉它Digest::MD5.hexdigest('password')
然后它作为 BLOB 进入。
现在,如果我添加anything到摘要创建的字符串上,然后就可以了!
def encrypt_password
self.password = Digest::MD5.hexdigest(self.password) + ' '
end
这他妈到底是什么??所以现在我的练习是添加一个换行符然后将其删除:
def encrypt_password
self.password = (Digest::MD5.hexdigest(self.password) + "\n").chomp
end
我觉得我应该在 Rails 的某个地方开一张票,但这太奇怪了,我不想因为甚至暗示可能会发生这样的事情而永远被社区嘲笑!