在我的web应用程序上使用Rails 4和Desive 3.1.0.我写了一个Cumber测试来测试用户注册;从邮箱中单击"确认我的帐户"链接时失败.

Scenario: User signs up with valid data                                                           # features/users/sign_up.feature:9
    When I sign up with valid user data                                                             # features/step_definitions/user_steps.rb:87
    Then I should receive an email                                                                  # features/step_definitions/email_steps.rb:51
    When I open the email                                                                           # features/step_definitions/email_steps.rb:76
    Then I should see the email delivered from "no-reply@mysite.com"                                # features/step_definitions/email_steps.rb:116
    And I should see "You can confirm your account email through the link below:" in the email body # features/step_definitions/email_steps.rb:108
    When I follow "Confirm my account" in the email                                                 # features/step_definitions/email_steps.rb:178
    Then I should be signed in                                                                      # features/step_definitions/user_steps.rb:142
      expected to find text "Logout" in "...Confirmation token is invalid..." (RSpec::Expectations::ExpectationNotMetError)
     ./features/step_definitions/user_steps.rb:143:in `/^I should be signed in$

当我通过web服务器手动注册时,这个错误也会重现,所以这似乎不是问题.

我想:

  • 用户可以通过此邮箱的链接一键确认其帐户
  • 让用户在确认其帐户后保持登录状态

我已经设置好了:

  • 最新设计代码,来自GitHub(3.1.0,参考041fcf90807df5efded5fdcd53ced80544e7430f)
  • 实现confirmableUser
  • 使用"默认"确认控制器(我还没有定义自己的自定义控制器.)

我读过以下帖子:

并try :

  • 在我的Desive初始值设定项中设置config.allow_insecure_tokens_lookup = true,这会在启动时抛出"未知方法"错误.另外,听起来这只是一个临时修复,所以我想避免使用它.
  • 清除了我的数据库并从头开始(因此不存在旧令牌)

Update:

Checking the confirmation token stored on the User after registering. The emails token matches the DBs token. According to the posts above, the new Devise behavior says not supposed to, and that instead it is should generate a second token based on the e-mail's token. This is suspicious. Running User.confirm_by_token('[EMAIL_CONFIRMATION_TOKEN]') returns a User who has errors set "@messages={:confirmation_token=>["is invalid"]}", which appears to be the source of the issue.

不匹配的 token 似乎是问题的核心;在console中运行以下代码以手动更改用户的确认令牌会导致确认成功:

new_token = Devise.token_generator.digest(User, :confirmation_token, '[EMAIL_TOKEN]')
u = User.first
u.confirmation_token = new_token
u.save
User.confirm_by_token('[EMAIL_TOKEN]') # Succeeds

那么,为什么它首先要将错误的确认令牌保存到DB中呢?我正在使用自定义注册控制器...可能是因为它里面有什么东西导致它被错误地设置了?

routes.rb

  devise_for  :users,
          :path => '',
          :path_names => {
            :sign_in => 'login',
            :sign_out => 'logout',
            :sign_up => 'register'
            },
          :controllers => {
            :registrations => "users/registrations",
            :sessions => "users/sessions"
          }

users/registrations_controller.rb:

class Users::RegistrationsController < Devise::RegistrationsController

  def create
    # Custom code to fix DateTime issue
    Utils::convert_params_date_select params[:user][:profile_attributes], :birthday, nil, true

    super
  end

  def sign_up_params
    # TODO: Still need to fix this. Strong parameters with nested attributes not working.
    #       Permitting all is a security hazard.
    params.require(:user).permit!
    #params.require(:user).permit(:email, :password, :password_confirmation, :profile_attributes)
  end
  private :sign_up_params
end

推荐答案

所以升级到Desive 3.1.0给我留下了一些我已经有一段时间没碰过的"污点".

根据this blog post,你需要将你的Desive mailer改为@token而不是原来的@resource.confirmation_token.

app/views/<user>/mailer/confirmation_instructions.html.erb中找到这个,并将其更改为:

<p>Welcome <%= @resource.email %>!</p>
<p>You can confirm your account email through the link below:</p>
<p><%= link_to 'Confirm my account', confirmation_url(@resource, :confirmation_token => @token) %></p>

这将修复您遇到的任何基于令牌的确认问题.这可能会修复任何解锁或重置密码令牌的问题.

Ruby-on-rails相关问答推荐

使用Hotwire/Turbo的Rails在链接悬停时获取请求

Rails 6升级没有加载Mongoid,这是一个问题

Rails 7.1,登录到STDOUT和LOG/Production.log

如何从数组中提取值

rails turbo frame 显然在更新,但浏览器窗口保持不变

如何在 Rails 中声明动态路由范围/命名空间变量?

Rails 7 应用程序 - 引用模型文件时出现未初始化常量错误

设计:手动加密密码并直接存储

在命名空间内设计

为什么使用 HTTP PUT 和 DELETE 方法而不是 POST?

使用devise gem点击确认链接后避免登录?

可能在rails中有多态has_one关系?

使用 RSpec 2 关闭一个规范的事务性固定装置

如何使用 Ruby 在现有 PDF 上编辑或书写?

Ruby 和 Ruby on Rails 离线 API 文档

设计记住我和会话

控制器 helper_method

如何在 Ruby 中搜索数组?

Rails 在 id 字段上重置种子的方法

如何测试也定义为辅助方法的 ApplicationController 方法?