在我的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)
- 实现
confirmable
的User
类 - 使用"默认"确认控制器(我还没有定义自己的自定义控制器.)
我读过以下帖子:
- Devise confirmation_token is invalid
- Devise 3.1: Now with more secure defaults
- GitHub Issue - Devise confirmation_token invalid
并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