用户注册时设计“确认令牌无效”
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了用户注册时设计“确认令牌无效”相关的知识,希望对你有一定的参考价值。
在我的网络应用程序上使用Rails 4和Devise 3.1.0。我写了一个Cucumber测试来测试用户注册;从电子邮件中单击“确认我的帐户”链接时失败。
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服务器手动注册时,此错误也是可重现的,因此它似乎不是黄瓜问题。
我想要:
- 用户只需单击一下即可通过此电子邮件的链接确认其帐户
- 让用户在确认帐户后保持登录状态
我有设置:
- 最新的Devise代码,来自GitHub(3.1.0,ref 041fcf90807df5efded5fdcd53ced80544e7430f)
- 实施
User
的confirmable
类 - 使用'默认'确认控制器(我没有定义自己的自定义控制器。)
我看过这些帖子:
- Devise confirmation_token is invalid
- Devise 3.1: Now with more secure defaults
- GitHub Issue - Devise confirmation_token invalid
并尝试过:
- 在我的Devise初始化程序中设置
config.allow_insecure_tokens_lookup = true
,它会在启动时抛出“未知方法”错误。另外,听起来这只是一个临时修复,所以我想避免使用它。 - 清除我的数据库并从头开始(所以没有旧的令牌存在)
更新:
注册后检查存储在User
上的确认令牌。电子邮件令牌与DB令牌匹配。根据上面的帖子,新的Devise行为说不应该,而是应该根据电子邮件的令牌生成第二个令牌。这是可疑的。运行User.confirm_by_token('[EMAIL_CONFIRMATION_TOKEN]')
会返回一个设置错误的用户“@messages = {:confirmation_token => [”无效“]}”,这似乎是问题的根源。
不匹配的令牌似乎是问题的核心;在控制台中运行以下代码以手动更改用户的confirmation_token导致确认成功:
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
那么为什么它首先将错误的确认令牌保存到数据库中呢?我正在使用自定义注册控制器...也许有一些东西导致它被错误地设置?
的routes.rb
devise_for :users,
:path => '',
:path_names => {
:sign_in => 'login',
:sign_out => 'logout',
:sign_up => 'register'
},
:controllers => {
:registrations => "users/registrations",
:sessions => "users/sessions"
}
用户/ 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
因此,升级到Devise 3.1.0会让我有些“残缺”,因为我有一段时间没有触及过。
根据this blog post,你需要改变你的Devise邮件使用@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>
这应该可以解决您遇到的任何基于令牌的确认问题。这可能会修复任何解锁或重置密码令牌问题。
我的一个朋友刚刚发现了这个问题并通过电子邮件发送给我,询问我是否已经弄清楚这一点,这提醒我,我从未提交过自己的答案,所以这里有:)
我最终重置了令牌并使用send
来获取原始令牌。这很丑陋,但它对devise (3.5.1)
起作用。
26 it "should auto create org" do
27 email = FG.generate :email
28 visit new_user_registration_path
29 fill_in :user_name, with: 'Ryan Angilly'
30 fill_in :user_user_provided_email, with: email
31 fill_in :user_password, with: '1234567890'
32
33 expect do
34 click_button 'Continue'
35 end.to change { Organization.count }.by(1)
36
37 expect(page.current_path).to eq(confirmation_required_path)
38 u = User.where(email: email).first
39 u.send :generate_confirmation_token
40 email_token = u.instance_variable_get(:@raw_confirmation_token)
41 u.save!
42 os = u.organizations
43 expect(os.size).to eq(1)
44 visit user_confirmation_path(confirmation_token: email_token)
45 o = os.first
46
47 u.reload
48 expect(u.confirmed?)
49 expect(page.current_url).to eq(organization_getting_started_url(o))
50 end
从设计3.5.2开始,确认令牌在确认过程中不再被消化。这意味着电子邮件中的令牌将与数据库中的令牌匹配。
在弄清楚这个之后我仍然遇到确认问题,但在我的情况下,当我超越find_first_by_auth_conditions
时,它被证明是我引入的一个错误。通过修复我在该方法中引入的错误,我通过确认修复了错误。
以上是关于用户注册时设计“确认令牌无效”的主要内容,如果未能解决你的问题,请参考以下文章
当 ViewPager 中的片段出现和消失时如何执行一些代码
Express实战 - 应用案例- realworld-API - 路由设计 - mongoose - 数据验证 - 密码加密 - 登录接口 - 身份认证 - token - 增删改查API(代码片段