You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Pundit为所有控制器动作授权?是否应采用该方案?

用Pundit实现全局控制器动作授权(管理员全权限,Editor默认全拒再开白名单)

1. 编写基础父Policy(ApplicationPolicy)

所有业务Policy都继承这个类,实现全局默认权限规则:

# app/policies/application_policy.rb
class ApplicationPolicy
  attr_reader :user, :record

  def initialize(user, record)
    @user = user
    @record = record
    raise Pundit::NotAuthorizedError, "必须登录才能操作" unless user
  end

  # 默认所有动作仅允许管理员访问,Editor无权限
  def index?; admin?; end
  def show?; admin?; end
  def create?; admin?; end
  def new?; admin?; end
  def update?; admin?; end
  def edit?; admin?; end
  def destroy?; admin?; end

  private
  # 判断是否为管理员
  def admin?
    user.role == 'admin'
  end

  # 预留Editor判断方法,后续开权限用
  def editor?
    user.role == 'editor'
  end
end

2. 业务Policy继承父类

比如CD资源的Policy,默认继承所有父类的权限规则,后续需要给Editor开权限时再重写对应方法:

# app/policies/cd_policy.rb
class CdPolicy < ApplicationPolicy
  # 示例:后续允许Editor创建和更新CD信息时,取消注释以下代码
  # def create?; admin? || editor?; end
  # def update?; admin? || editor?; end
end

3. 全局控制器授权(避免逐个动作写authorize)

在ApplicationController中添加全局授权逻辑,所有控制器的所有动作都会自动触发权限校验:

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  include Pundit::Authorization

  # 全局校验所有动作权限,可在特定控制器跳过
  before_action :authorize_request

  private
  def authorize_request
    # 自动匹配当前控制器对应的Policy类
    policy_class = "#{controller_name.classify}Policy".constantize
    # 根据动作类型处理record参数(适配index/new等无需实例的动作)
    record = case action_name
             when 'new', 'create'
               controller_name.classify.constantize.new
             when 'index'
               controller_name.classify.constantize
             else
               send(controller_name.singularize) # 比如show/edit动作取@cd实例
             end
    # 触发对应动作的权限校验
    authorize(record, "#{action_name}?")
  end

  # 处理授权失败的提示
  rescue_from Pundit::NotAuthorizedError do |_e|
    redirect_to root_path, alert: "无权限执行此操作"
  end
end

4. 跳过特定动作的授权(可选)

如果有不需要权限校验的页面(比如首页),在对应控制器中添加跳过逻辑:

# app/controllers/home_controller.rb
class HomeController < ApplicationController
  skip_before_action :authorize_request, only: [:index]

  def index; end
end

核心逻辑说明

  • 管理员默认拥有所有控制器所有动作的权限
  • Editor默认被拒绝所有操作,后续需要开放某个控制器的某个动作时,只需在对应业务Policy中重写该动作的校验方法(比如def create?; admin? || editor?; end)
  • 全局授权逻辑避免了在每个控制器每个动作中重复编写authorize调用,减少冗余代码

内容的提问来源于stack exchange,提问作者fugee ohu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 12:43:09