升级到设计3.1 =>获取重置密码令牌无效

And*_*tad 40 ruby-on-rails devise rspec2 ruby-on-rails-4 factory-bot

感谢史蒂文哈曼的这个要点,我得到了它的工作.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
Run Code Online (Sandbox Code Playgroud)

我将文件添加devise_mail_helpers.rb到功能规格所在的文件夹中并编写了此规范.

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
Run Code Online (Sandbox Code Playgroud)

这将照顾规范,使其在浏览器中工作,看看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--'
Run Code Online (Sandbox Code Playgroud)

我将密钥添加到设计初始化程序.

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

Reset password token is invalid
Run Code Online (Sandbox Code Playgroud)

似乎在电子邮件中发送的令牌不正确.其他一切都在发挥作用.我像温暖的刀槽黄油一样进出.

更新

现在我想,它必须是reset_password_token功能规范中的Here 加密:

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")
Run Code Online (Sandbox Code Playgroud)

发生的错误是:

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"
Run Code Online (Sandbox Code Playgroud)

关于我失踪的任何想法?

Dav*_*ner 91

您之前对我的类似问题发表了评论,我找到了一个可能对您有帮助的答案.

升级到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>
Run Code Online (Sandbox Code Playgroud)

这应该可以解决您遇到的任何基于令牌的确认问题.这也可能解决任何解锁或确认令牌问题.


小智 8

仅供参考,如果您尝试通过其他方式(即不同的邮件程序)发送重置密码令牌,您可以在您的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
Run Code Online (Sandbox Code Playgroud)


Ser*_*eev 7

我猜你已经将Devise升级到v3.1而不是v3.01,因为config.secret_key.所以我认为它与新的设计功能 - 秘密密钥有某种关联.
我找到了两个秘密密钥功能的提交,有助于更好地理解: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/上找到对您有用的内容.
您也可以在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,如图所示这里,而不是直接从资源获取令牌;


Nea*_*eal 7

我在规格上有这个错误.我试图手动设置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
Run Code Online (Sandbox Code Playgroud)