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

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

但是,完全相同的代码在本地通过rails s 。 电子邮件发送,我实际上可以重置密码。 我使用的代码只是标准的devise代码,我没有覆盖任何它。

也许这是与Apache的东西? 我不太熟悉它。 有没有人有任何想法?

检查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 )创build链接,而不是存储在数据库中的散列值。

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

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

编辑:阐述:

当你说'devise:可注册,:可跟踪,…'时,devise为你的模型增加了function。

在您的用户模型(或pipe理员等)中,您可以覆盖名为find_first_by_auth_conditions的Devise方法。 devise逻辑使用此特殊方法来查找正试图login的logging。 devise传入一个名为warden_conditions的参数中的一些信息。 这将包含一个电子邮件,一个用户名或一个reset_password_token,或其他任何你添加到你的deviselogin表单(如帐户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 

但是,上面的代码将打破密码重置function,因为devise是使用令牌来定位logging。 用户不input电子邮件,他们通过URL中的查询stringinput令牌,该查询string将传递给此方法以尝试查找logging。

因此,当你重写这个特殊的方法时,你需要使它更加健壮以解决密码重置的情况:

 (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 

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

 web_1 | <p><a href=3D"http://localhost:3000/admin/password/edit?reset_password_to= web_1 | ken=3DJ5Z5g6QNVQb3ZXkiKjTx">Change password</a></p> 

在这种情况下,使用3DJ5Z5g6QNVQb3ZXkiKjTx作为标记将不起作用,因为=3D实际上是an =字符编码。

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

如果您正在使用自定义确认邮件视图,则可能还需要注意(除了@ doctororange的邮寄后)以下内容。

视图中的链接也改变了。 这是新的链接代码:

 <p><%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %></p> 

这是旧链接代码:

 <p><%= link_to 'Confirm my account', user_confirmation_url(@resource, :confirmation_token => @resource.confirmation_token) %></p>