cancancanauthorize_resource 未按预期工作

问题描述 投票:0回答:3

我在简单的 cancancan 授权中遇到了意外的行为。

能力.rb

class Ability
  include CanCan::Ability

  def initialize(user)
    # Define abilities for the passed in user here. For example:
    #
    user ||= User.new # guest user (not logged in)
    if user.is_admin?
        can :manage, :all
    elsif user.is_standard?
        can :manage, ServiceOrder, {user_id: user.id}
        can :manage, ServiceOrderDetail, :service_order => { :user_id => user.id }
    end

service_order.rb 控制器(部分显示)

class ServiceOrdersController < ApplicationController
  authorize_resource

  def show
    @service_order = ServiceOrder.includes(:service_order_details).find(params[:id])
  end

end

这不起作用,因为它让控制器显示任何 service_order 记录,而不仅仅是 current_user 拥有的记录。

唯一有效的方法是我手动授权控制器添加:

authorize! :show, @service_order

像这样:

  def show
    @service_order = ServiceOrder.includes(:service_order_details).find(params[:id])
    authorize! :show, @service_order
  end

这毫无意义,因为

authorize_resource
应该这样做。

ruby-on-rails cancan cancancan
3个回答
10
投票

发生的事情是

authorize_resource
在显示操作之前发生,并且由于
@service_order
尚未设置,因此它正在针对类进行检查,并且用户确实有权在约束下显示
ServiceOrder

添加authorize_resource将安装一个调用authorize!的before_action回调,并传递资源实例变量(如果存在)。如果未设置实例变量(例如在索引操作中),它将传入类名。例如,如果我们有一个 ProductsController,它将在每个操作之前执行此操作。

授权!(params[:action].to_sym,@product || 产品)

来自 Cancancan 文档

您需要做的是

load_and_authorize_resource
,按照widjajayd 的建议。或者(如果您不想使用 cancancan 默认加载操作)执行
before_filter
,在
authorize_resource
调用之前使用您的自定义方法手动加载资源。


2
投票

我的建议:使用 load_and_authorize_resource 代替authorize_resource,下面是控制器的示例 只需确保您的strong_parameters声明:service_order_params

  load_and_authorize_resource param_method: :service_order_params

0
投票

当在控制器顶部使用

authorize_resource
时,它实际上设置了一个before_action,它将在控制器操作之前完成授权检查,因此必须在控制器操作之前设置实例变量(而不是在控制器操作内部) ),即您必须使用 before_action 来设置实例变量。 示例

class PostsController < ApplicationController authorize_resource # rest of controller

authorize_resource 

创建的before_action将查找必须在before_action中创建的

@post
实例变量(或索引操作的
@posts
)(而不是在控制器操作中,因为授权检查已经在控制器操作运行的时间)。
资源

该信息来自

authorize_resource

方法的 cancancan 源代码/文档


设置一个使用实例变量授权资源的 before 过滤器。例如,如果您有一个 ArticlesController,它将检查 @article 实例变量并确保用户可以对其执行当前操作。在幕后它正在做类似以下的事情:

authorize!(params[:action].to_sym, @article || Article)


    

© www.soinside.com 2019 - 2024. All rights reserved.