我有一个Rails 3.2.22应用程序在生产中运行1年,它使用Devise来验证用户。
我正在尝试实施令牌身份验证,因此我可以使用名为简单令牌身份验证的Gem https://github.com/gonzalo-bulnes/simple_token_authentication
发送带有URL params的事务电子邮件,该URL params可以自动登录用户按照所有说明操作后,我用before_filter :authenticate_user!
替换了控制器中的acts_as_token_authentication_handler_for User
。
gem与Devise集成并且默认后退,因此不再需要在控制器中调用devise;如果令牌中缺少令牌(或错误),Devise将接管。
在我的测试中,如果我将此行添加到ApplicationController
,一切正常,我可以使用gem生成的authentication_token=
秘密登录用户。
但我不需要auth
用于ApplicationController,我需要它用于其他控制器(如DashboardController),url是/ dashboard
如果我将acts_as_token_authentication_handler_for User
放入该控制器(替换Devise的电话),我会得到最奇怪的情况。
使用binding.pry,我可以确认在加载模板期间正确设置了current_user
。
但模板中有一点使用@last_emails,它是在ApplicationController
中的方法中定义的。
使用binding.pry,我可以确认current_user
nil 。
这是代码:
class DashboardController < ApplicationController
layout 'material'
acts_as_token_authentication_handler_for User
在ApplicationController中:
class ApplicationController < ActionController::Base
layout 'omega'
before_filter :populate_last_contacts_for_menu
private
def populate_last_contacts_for_menu
if current_user
@last_contacts = Contact.where("user_id" => current_user.id).where('blocked != ? or blocked is null', true).last(10).reverse
end
end
有趣的是:使用binding.pry,就像我说的,我可以检查模板中是否定义了current_user(这意味着sign_in成功)。它甚至在更好的错误控制台中定义。但是,如果我去主页,我看到用户没有登录...
我已经浏览了整个网络:阅读Gem的github中的所有问题以及SO中关于current_user为零的所有帖子,但根本没有亮点。
我的devise_for :users
不在routes.rb的任何范围内,正如我所说,我在应用程序中有很多调用current_user,这是我第一次遇到Devise问题。
答案 0 :(得分:0)
当您在acts_as_token_authentication_handler_for
中调用DashboardController
指令时,它会为控制器声明一些before_filters
以对用户进行身份验证。
但问题是,当你继承rails控制器时,首先执行父控制器的过滤器,然后执行子控制器的过滤器。
父控制器为ApplicationController
。在调用它的populate_last_contacts_for_menu
过滤器时,用户未被认证,因为acts_as_token_authentication_handler_for
指令给出的认证过滤器尚未调用,它们在子控制器中声明。
可能的解决方案:
1)尝试附加populate_last_contacts_for_menu
过滤器:
append_before_filter :populate_last_contacts_for_menu
我不确定它会对你的情况有效,但你可以尝试找出它。
2)调用acts_as_token_authentication_handler_for
中的ApplicationControoler
指令,并以某种方式跳过不需要它的控制器。 (我不喜欢这样,但如果第一个不起作用,它可能会有所帮助。)
3)将populate_last_contacts_for_menu
过滤器逻辑移动到帮助器中。我认为这是最好的解决方案。该逻辑不属于控制器。当请求不是“获取”时,此过滤器不执行任何操作,因为在这种情况下您不需要呈现视图。
module ApplicationHelper
def last_contacts
@last_contacts ||= if signed_in?
Contact.where("user_id" => current_user.id).where('blocked != ? or blocked is null', true).last(10).reverse
else
[]
end
end
...
end
# View:
<% if last_contacts.present? %>
....
<% end %>