CanCanCan权限控制:如何限制非管理员访问/admin/applications?
Hey there! This is a common hiccup when using CanCanCan with multiple routes interacting with the same underlying model. The issue arises because your manage oauth applications permission grants broad access to the Doorkeeper::Application model, which both /oauth/applications/* and /admin/applications rely on. Here are a few straightforward solutions to lock down the admin route exclusively to admins:
1. Quick Fix: Add a Before-Action to the Admin Controller
This is the simplest, most direct approach if the admin section should be strictly off-limits to non-admins.
Open your Admin::ApplicationsController and add a before-action that checks for admin status:
class Admin::ApplicationsController < ApplicationController # Run this check before any action in the controller before_action :require_admin # Your existing controller actions go here... private def require_admin # Redirect or deny access if the user isn't an admin unless current_user&.admin? redirect_to root_path, alert: "You don't have permission to access this page." # Alternatively, return a 403 forbidden response: # head :forbidden end end end
2. Integrate with CanCanCan's Ability System
If you prefer to keep all permission logic centralized in your Ability model, adjust your rules to explicitly restrict admin access:
First, update app/models/ability.rb:
class Ability include CanCan::Ability def initialize(user) user ||= User.new # Handle guest users if user.admin? # Admins get full access to everything can :manage, :all else # Non-admins can only manage OAuth applications via the Doorkeeper routes can :manage, Doorkeeper::Application # Explicitly block access to the admin section cannot :access, :admin end end end
Then, add an authorization check in your Admin::ApplicationsController:
class Admin::ApplicationsController < ApplicationController before_action :authorize_admin_access private def authorize_admin_access # Use CanCanCan's authorize! method to enforce the :access, :admin rule authorize! :access, :admin end end
3. Granular Control: Scope Abilities by Controller
If you need more nuanced permissions (e.g., some non-admins might have limited admin access), you can scope your abilities to specific controllers:
Update app/models/ability.rb:
class Ability include CanCan::Ability def initialize(user) user ||= User.new if user.admin? # Admins can manage applications through both controllers can :manage, Doorkeeper::Application else # Non-admins only get access to the Doorkeeper controller actions can [:index, :show, :new, :create, :edit, :update, :destroy], Doorkeeper::Application, controller: 'doorkeeper/applications' # Block all actions on the admin controller for non-admins cannot [:index, :show, :new, :create, :edit, :update, :destroy], Doorkeeper::Application, controller: 'admin/applications' end end end
Then ensure your admin controller uses CanCanCan's resource loading:
class Admin::ApplicationsController < ApplicationController load_and_authorize_resource class: Doorkeeper::Application end
Testing the Fix
After implementing any of these solutions, verify by:
- Logging in as a non-admin user with
manage oauth applicationspermission: They should be blocked from/admin/applicationsbut still access/oauth/applications/*. - Logging in as an admin: They should have full access to both paths.
内容的提问来源于stack exchange,提问作者Mirror318

