升级到devise3.1 =>重置密码令牌无效

由于这个要求,史蒂文·哈曼,我得到了它的工作。 devise_mail_helpers.rb

module Features module MailHelpers def last_email ActionMailer::Base.deliveries[0] end # Can be used like: # extract_token_from_email(:reset_password) def extract_token_from_email(token_name) mail_body = last_email.body.to_s mail_body[/#{token_name.to_s}_token=([^"]+)/, 1] end end end 

我将文件devise_mail_helpers.rb添加到function规格所在的文件夹中,并编写了这个规范。

 require 'devise_mail_helpers.rb' include Features include MailHelpers describe "PasswordResets" do it "emails user when requesting password reset" do user = FactoryGirl.create(:user) visit root_url find("#login_link").click click_link "Forgot your password?" fill_in "Email", :with => user.email click_button "Send instructions" current_path.should eq('/users/sign_in') page.should have_content("You will receive an email with instructions about how to reset your password in a few minutes.") last_email.to.should include(user.email) token = extract_token_from_email(:reset_password) # Here I call the MailHelper form above visit edit_password_url(reset_password_token: token) fill_in "user_password", :with => "foobar" fill_in "user_password_confirmation", :with => "foobar1" find('.signup_firm').find(".submit").click page.should have_content("Password confirmation doesn't match Password") end end 

这照顾的规范,使其在浏览器中查看下面的Dave的答案。

原来的问题

在我的rails 4应用程序中,我已经升级到3.1并运行rails s ,然后我得到这个:

 `raise_no_secret_key': Devise.secret_key was not set. Please add the following to your Devise initializer: (RuntimeError) config.secret_key = '--secret--' 

我将秘密密钥添加到devise初始值设定项中。

之后,当我尝试重置密码时,出现以下错误

 Reset password token is invalid 

这似乎是在邮件中发送的令牌不正确。 其他一切正在工作。 我像一个温暖的刀槽黄油一样login和注销。

更新

现在我想,这是必须的东西encryption的reset_password_token这里从function规格:

 user = FactoryGirl.create(:user, :reset_password_token => "something", :reset_password_sent_at => 1.hour.ago) visit edit_password_url(user, :reset_password_token => user.reset_password_token) fill_in "user_password", :with => "foobar" click_button "Change my password" page.should have_content("Password confirmation doesn't match Password") 

发生的错误是:

 Failure/Error: page.should have_content ("Password confirmation doesn't match Password") expected to find text "Password confirmation doesn't match Password" in "Reset password token is invalid" 

任何想法,我失踪?

您之前对我的类似问题进行了评论,我find了一个可能对您有帮助的答案。

升级到Devise 3.1.0,留下了一段时间以来我没有碰到过的东西。 根据这个博客文章 ,你需要改变你的devise邮件使用@token而不是旧的@resource.confirmation_token

app/views/<user>/mailer/reset_password_instructions.html.erb它并将其更改为如下所示:

 <p>Hello <%= @resource.email %>!</p> <p>Someone has requested a link to change your password, and you can do this through the link below.</p> <p><%= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @token) %></p> <p>If you didn't request this, please ignore this email.</p> <p>Your password won't change until you access the link above and create a new one.</p> 

这应该修复您正在使用的任何基于令牌的确认问题。 这可能会解决任何解锁或确认令牌问题。

仅供参考,如果您尝试通过其他方式(即不同的邮件程序)发送重置密码令牌,则可以在您的User类中使用这样的代码(从Devise源代码中挖掘出来):

 def send_invitation raw, enc = Devise.token_generator.generate(self.class, :reset_password_token) self.reset_password_token = enc self.reset_password_sent_at = Time.now.utc self.save(:validate => false) Notifier.signup_notification(contactable: self, token: raw).deliver end 

我猜你已经把Devise升级到v3.1而不是v3.01,因为config.secret_key 。 所以我认为这是与新的devisefunction – 密钥有关。
我发现了两个提交秘密密钥的function,可以帮助更好地理解: https : //github.com/plataformatec/devise/commit/32648027e282eb4c0f4f42e9c9cc0c961765faa8 https://github.com/plataformatec/devise/commit/d56641f514f54da04f778b2a9b816561df7910c2

也许你会在http://blog.plataformatec.com.br/2013/08/devise-3-1-now-with-more-secure-defaults/上find对你有用的东西&#x3002;
你也可以通过https://github.com/plataformatec/devise/compare/v3.0…v3.1.0 grep reset_password_token

编辑
阅读http://blog.plataformatec.com.br/2013/08/devise-3-1-now-with-more-secure-defaults/

  • Devise邮件程序现在在每个方法上接收一个额外的标记参数。 如果你已经定制了Devise邮件,你将不得不更新它。 所有的邮件程序视图也需要更新为使用@token ,如图所示,而不是直接从资源获取令牌;

我在规格上有这个错误。 我试图在用户上手动设置reset_password_token ,这样我就可以将令牌传递给edit_user_password_path 。 但是,重置令牌被散列,因此手动设置将不起作用。 哎呀! 为了避免这个错误,我设置了reset_token等于由user.send_reset_password_instructions返回的实际标记。

工作规范:

 require 'spec_helper' feature 'User resets password' do scenario 'fills out reset form' do user = create(:user) reset_token = user.send_reset_password_instructions new_password = 'newpassword!' visit edit_user_password_path(user, reset_password_token: reset_token) fill_in :user_password, with: new_password fill_in :user_password_confirmation, with: new_password click_button 'Change my password' expect(page).to have_content( 'Your password was changed successfully. You are now signed in.' ) end end 

在您的设备重置密码模板中,确保以下内容应该正确:

= link_to'更改我的密码',edit_password_url(@resource,:reset_password_token => @token)

正如其他人所指出的:原因是生成包含重置密码链接的邮件的视图需要更改。

我看到这个错误,因为我还在使用devise-i18n-views gem,它会生成旧的链接。 去掉这个gem,依靠现在是devise-i18n的一部分的意见,解决了我的问题。