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>