CanCan错误地拒绝管理员访问



我正在处理别人的代码,而且我对Rails相当缺乏经验,CanCan&发明

当尝试登录时(使用我知道的凭据,就像以前一样,我已经检查了数据库并成功使用了重置功能),我会收到一个错误屏幕。

CanCan::AccessDenied in AdminController#index
You are not authorized to access this page.
app/controllers/admin_controller.rb:4:in `index'
config/initializers/quiet_assets.rb:6:in `call_with_quiet_assets'

并且在终端中

Started POST "/users/sign_in" for 127.0.0.1 at 2012-11-14 13:13:01 +0000
Processing by Devise::SessionsController#create as HTML
Parameters: {"utf8"=>"✓",  "authenticity_token"=>"T8CJkCIEA3r7ROiknVp/vbEgeKCBZEjl3uYd+46G7no=", "user"=>{"email"=>"pass@user.com", "password"=>"[FILTERED]", "remember_me"=>"0"}, "commit"=>"Sign in"}
WARNING: Can't verify CSRF token authenticity
User Load (0.3ms)  SELECT `users`.* FROM `users` WHERE `users`.`email` = 'pass@user.com' LIMIT 1
(0.2ms)  BEGIN
(0.3ms)  UPDATE `users` SET `last_sign_in_at` = '2012-11-14 11:10:56', `current_sign_in_at` = '2012-11-14 13:13:01', `sign_in_count` = 219, `updated_at` = '2012-11-14 13:13:01' WHERE `users`.`id` = 1
(0.1ms)  COMMIT
Redirected to http://core.lvh.me:3000/admin
Completed 302 Found in 355ms

Started GET "/admin" for 127.0.0.1 at 2012-11-14 13:13:02 +0000
Processing by AdminController#index as HTML
Completed 500 Internal Server Error in 265ms
CanCan::AccessDenied (You are not authorized to access this page.):
app/controllers/admin_controller.rb:4:in `index'
config/initializers/quiet_assets.rb:6:in `call_with_quiet_assets'

admin_controller.rb

class AdminController < ApplicationController
def index
authorize! :index, :admin (#line 4)
end

ability.rb

class Ability
include CanCan::Ability
def initialize(user)
user ||= User.new # guest user (not logged in)
case user.role_name
when "super_admin"
# can do everything
can :manage, :all
when "franchise_admin"
can [:read, :search, :all, :up_down_index], Article
can [:old_feed, :sites, :new_feed], MobileFeed
can [:new, :read, :update], SiteSpecificArticle, site_id: user.site_id
can [:index, :new_site_essentials], :admin

when "franchise_editor"
can [:new, :read, :update], SiteSpecificArticle { |ssa| ssa.site.customer.sites.include?(user.site) }
can [:old_feed, :sites, :new_feed], MobileFeed
can [:read, :search, :all, :up_down_index], Article
when "site_admin"
# can CRUD users for their site
can :manage, User, site_id: user.site_id
# can edit content for their site
can [:read, :update], ArticleSitePermission, site_id: user.site_id
can [:read, :update], CoreArticleSiteVisibility, site_id: user.site_id
can [:new, :read, :update], SiteSpecificArticle, site_id: user.site_id
can [:new, :read, :update], FrontPageCampaign, site_id: user.site_id
can [:new, :read, :update], FrontPageTimeBasedArticle, site_id: user.site_id
can [:new, :read, :update], FrontpageArticle, site_id: user.site_id
can [:index, :new_site_essentials], :admin
can [:read, :search, :all, :up_down_index, :hidden_in_this_site], Article
can [:old_feed, :sites, :new_feed], MobileFeed
can [:index, :create], TrackMood
can :site_styles, Site
when "editor"
# can edit content for their site
can [:read, :update], ArticleSitePermission, site_id: user.site_id
can [:read, :update], CoreArticleSiteVisibility, site_id: user.site_id
can [:new, :read, :update], SiteSpecificArticle, site_id: user.site_id
can :manage, FrontPageCampaign, site_id: user.site_id
can :manage, User, site_id: user.site_id
can [:new, :read, :update], FrontPageTimeBasedArticle, site_id: user.site_id
can [:new, :read, :update], FrontpageArticle, site_id: user.site_id
can [:old_feed, :sites, :new_feed], MobileFeed
can [:index, :new_site_essentials], :admin
can [:read, :search, :all, :up_down_index, :hidden_in_this_site], Article
can [:index, :create], TrackMood
can :site_styles, Site
else
# guest user (not logged in)
can [:read, :search, :up_down_index], Article
can [:old_feed, :sites, :new_feed], MobileFeed
can [:index, :create], TrackMood
can :site_styles, Site
end
end
end

如能在这件事上提供任何帮助,我们将不胜感激。即使这只是调试问题的又一步。

谢谢

Github上的CanCan wiki声明:

添加authorize_resource将生成一个调用authorize!的before筛选器,如果资源实例变量存在,则传递该变量。如果实例变量没有设置(例如在索引操作中),则它将传递类名。例如,如果我们有一个ProductsController,则它会在每次操作之前执行此操作。

authorize!(params[:action], @product || Product)

您的问题是,当您实际上必须授权管理对象或模型时,您正试图授权:admin符号的:index操作,例如:

authorize!(:index, @admin)

我想你误会授权了!方法,并试图授权角色admin的索引操作,但所有CanCan内容都是基于current_ability授权的,current_ability应该是登录后在用户会话上设置的第一个内容。CanCan可以为您这样做,使用默认的ApplicationController方法:

def current_ability
@current_ability ||= Ability.new(current_user)
end

但这意味着您需要另一个名为current_user的方法来返回当前用户(doh)。检查你是否设置了这个,如果没有,那么设置它并将:admin更改为@admin(你必须实例化它,我认为它类似于current_user.admin(?))。

还有一件事:如果你这样做只是为了调试,好吧,没问题,但如果你真的想这样授权每个动作,请不要。CanCan有一个名为load_and_authorize_resource的方法,它既为控制器的每个操作授权current_user,又将变量@model(例如@products)实例化为:Product.accessible_by(current_ability)。当你有一些用户只能在某些情况下看到或管理的东西时,比如编辑他们自己的个人资料,这种方法效果很好。当然,您必须在ability.rb文件中进行设置。这种方法是这样的:

class AdminController < ApplicationController
load_and_authorize_resource
def index
# @admins here will have every admin that the user can see
end
end

如果你有一些不需要授权的行动,你可以说:

load_and_authorize_resource, :only => [:action1, :action2]
load_and_authorize_resource, :except => [:action1, :action2]

或者:

load_and_authorize_resource
skip_authorize_resource, :only => [:action1]
skip_authorize_resource, :except => :action2 #can be both an array or single symbol

我希望这能帮助你和任何有这个问题的人:)

您可以尝试更改为:

class AdminController < ApplicationController
def index
authorize! :index, :super_admin (#line 4)
end

相关内容

最新更新