Rails 4 + Devise:密码重置始终在生产服务器上提供"令牌无效"错误,但在本地工作正常.

jus*_*dao 48 ruby-on-rails devise ruby-on-rails-4

我有一个Rails 4应用程序设置为使用Devise,我正在运行密码重置问题.我有邮件设置,密码重置电子邮件发送正常.提供的链接具有分配给它的正确reset_password_token,我使用该数据库检查了该链接.但是,当我使用格式正确的密码提交表单时,会出现错误,指出重置令牌无效.

但是,完全相同的代码在本地工作正常rails s.电子邮件发送,我实际上可以重置密码.我使用的代码只是标准的Devise代码,我没有覆盖任何代码.

也许这与Apache有关?我不太熟悉它.有没有人有任何想法?

doc*_*nge 127

检查代码 app/views/devise/mailer/reset_password_instructions.html.erb

该链接生成:

edit_password_url(@resource, :reset_password_token => @token)

如果您的视图仍然使用此代码,那么这将是问题的原因:

edit_password_url(@resource, :reset_password_token => @resource.password_reset_token)

Devise开始存储令牌的哈希值,因此电子邮件需要使用真实令牌(@token)而不是存储在数据库中的散列值来创建链接.

这种变化发生在143794d701的 Devise中

  • 我遇到了同样的问题,在更改edit_password_url以使用@token后仍然会发生这种情况.知道还有什么可以导致这个吗?谢谢! (2认同)
  • 非常感谢你.在那里浪费了将近一个小时. (2认同)

Max*_*nus 11

除了doctororange的修复,如果你要覆盖resource.find_first_by_auth_conditions,你需要考虑warden_conditions包含reset_password_token而不是电子邮件或用户名的情况.

编辑:详细说明:

当您说'设计:可注册,可跟踪,......'时,Devise会为您的模型添加功能.

在用户模型(或管理员等)中,您可以覆盖名为find_first_by_auth_conditions的Devise方法.Devise逻辑使用此特殊方法来查找尝试登录的记录.Devise在一个名为warden_conditions的参数中传递一些信息.这将包含电子邮件,用户名或reset_password_token,或您添加到设计登录表单中的任何其他内容(例如帐户ID).

例如,您可能会看到如下内容:

(app/models/user.rb)
class User

  ...

  def self.find_first_by_auth_conditions warden_conditions
    conditions = warden_conditions.dup

    if (email = conditions.delete(:email)).present?
      where(email: email.downcase).first
    end
  end

end
Run Code Online (Sandbox Code Playgroud)

但是,上面的代码将破坏密码重置功能,因为设计使用令牌来定位记录.用户不输入电子邮件,他们通过URL中的查询字符串输入令牌,该字符串将传递给此方法以尝试查找记录.

因此,当您覆盖此特殊方法时,您需要使其更加健壮以解决密码重置情况:

(app/models/user.rb)
class User

  ...

  def self.find_first_by_auth_conditions warden_conditions
    conditions = warden_conditions.dup

    if (email = conditions.delete(:email)).present?
      where(email: email.downcase).first
    elsif conditions.has_key?(:reset_password_token)
      where(reset_password_token: conditions[:reset_password_token]).first
    end
  end

end
Run Code Online (Sandbox Code Playgroud)


yba*_*art 5

如果您从日志中获取URL,它可能如下所示:

web_1      | <p><a href=3D"http://localhost:3000/admin/password/edit?reset_password_to=
web_1      | ken=3DJ5Z5g6QNVQb3ZXkiKjTx">Change password</a></p>
Run Code Online (Sandbox Code Playgroud)

在这种情况下,使用3DJ5Z5g6QNVQb3ZXkiKjTx令牌将无法工作,因为=3D它实际上是一个=字符编码.

在这种情况下,您需要使用J5Z5g6QNVQb3ZXkiKjTx(3D删除)

  • 你是个天才! (2认同)