重置设计 rails 的密码会导致“没有将数组隐式转换为字符串”错误

Posted

技术标签:

【中文标题】重置设计 rails 的密码会导致“没有将数组隐式转换为字符串”错误【英文标题】:Reset password for devise rails gives 'no implicit conversion of Array into String' error 【发布时间】:2018-12-24 13:04:41 【问题描述】:

我正在尝试使用默认设计密码控制器#create 方法重置密码,并且当设计尝试生成令牌时收到错误消息。这是使用 Rails 服务器进行开发的中断。

我没有自定义密码控制器,我只是使用此方法的默认设计控制器。

我已经尝试搜索,但没有发现类似的问题,除了看起来不相关的Ruby on Rails: no implicit conversion of Array into String (DEVISE)。我尝试清除 Rails 缓存并使用隐身浏览器,但这并没有改变任何东西。我现在正在寻找其他可以尝试的方法,但似乎碰壁了。

配置:

设计使用用户名而不是电子邮件进行身份验证:

config.authentication_keys = [:username]
config.reset_password_keys = [:username]

我的用户被归类为“User::Admin”等,它看起来像:

class User < ApplicationRecord
  devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable
  validates :email, uniqueness: true
  validates :username, uniqueness: true
  validates :user_type, presence: true
  self.inheritance_column = :user_type

Image of Final Error Image

我的带有堆栈跟踪的日志:

Started POST "/users/password" for 127.0.0.1 at 2018-07-16 14:27:44         -0700
Processing by Users::PasswordsController#create as html
  Parameters: "utf8"=>"✓",    "authenticity_token"=>"rS7qFIRbbpd/M3QoAD1OLeDRDoliWAQK+PRE/qG2CgK2COvwwVCNFA6aMpcY0P81AEKo0fEpfNe4SRqLk7WDAw==", "user"=>"username"=>"timtim", "commit"=>"Send me reset password instructions"
  User Load (0.9ms)  SELECT  "users".* FROM "users" WHERE "users"."username" = $1 ORDER BY "users"."id" ASC LIMIT $2  [["username", "timtim"], ["LIMIT", 1]]
  ↳ /Users/timchipperfield/.rvm/gems/ruby-2.5.1/gems/activerecord-5.2.0/lib/active_record/log_subscriber.rb:98
Completed 500 Internal Server Error in 5ms (ActiveRecord: 0.9ms)


TypeError (no implicit conversion of Array into String):

/Users/timchipperfield/.rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/openssl/pkcs5.rb:14:in `pbkdf2_hmac'
/Users/timchipperfield/.rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/openssl/pkcs5.rb:14:in `pbkdf2_hmac'
/Users/timchipperfield/.rvm/rubies/ruby-2.5.1/lib/ruby/2.5.0/openssl/pkcs5.rb:19:in `pbkdf2_hmac_sha1'
activesupport (5.2.0) lib/active_support/key_generator.rb:23:in `generate_key'
activesupport (5.2.0) lib/active_support/key_generator.rb:38:in `generate_key'
devise (4.4.3) lib/devise/token_generator.rb:29:in `key_for'
devise (4.4.3) lib/devise/token_generator.rb:17:in `generate'
devise (4.4.3) lib/devise/models/recoverable.rb:90:in `set_reset_password_token'
devise (4.4.3) lib/devise/models/recoverable.rb:51:in `send_reset_password_instructions'
devise (4.4.3) lib/devise/models/recoverable.rb:136:in `send_reset_password_instructions'
devise (4.4.3) app/controllers/devise/passwords_controller.rb:15:in `create'

如果有帮助,堆栈跟踪“在”到达控制器之前还有很多内容。

我正在运行设计 (4.4.3),将 Passenger 作为我的应用程序服务器

我的环境看起来像:

ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-darwin17]
Rails 5.2.0
Bundler version 1.16.2
rvm 1.29.3

【问题讨论】:

【参考方案1】:

由于您使用的是 Rails 5.2.0,我猜您也将 secret_key_base 替换为 encrypted credentials。但是,默认情况下,devise 仍会尝试使用 secret_key_base 来生成安全哈希。

您应该会收到类似以下的错误:

TypeError in User::PasswordsController#create
no implicit conversion of Hash into String

def pbkdf2_hmac(pass, salt, iter, keylen, digest)
  OpenSSL::KDF.pbkdf2_hmac(pass, salt: salt, iterations: iter,
                               length: keylen, hash: digest)
end

有两种方法可以解决此问题:

1) 在 initializers/devise.rb 中取消注释 config.secret_key

config.secret_key = 'SOME_RANDOM_VALUE'

2) 将 SOME_RANDOM_VALUE 添加到 encrypted_credentials:

第一次运行:

rails credentials:edit

添加类似这样的一行:

devise:
  secret_key: SOME_RANDOM_VALUE

然后从设计初始化程序中调用该键:

config.secret_key = Rails.application.credentials.devise[:secret_key]

【讨论】:

这行得通。感谢@msdundar 的精彩、详细的回答。

以上是关于重置设计 rails 的密码会导致“没有将数组隐式转换为字符串”错误的主要内容,如果未能解决你的问题,请参考以下文章

Rails 4 + 设计:密码重置总是在生产服务器上给出“令牌无效”错误,但在本地工作正常。

Rails 重置密码电子邮件未触发

使用设计重置密码问题

使用设计发送重置密码说明

Rails 密码重置记录未找到

持有发送重置密码的电子邮件,直到某个指示器设置为rails