2

users/1/edit当我以其他用户身份登录时访问不会引发 AccessDenied 错误,我不知道为什么:

  authorize_resource only: [:edit, :update]
  def edit
    @user = User.find(params[:id])
  end
  def update
    @user = User.find(params[:id])
    if @user.update_attributes(params[:user])
      redirect_to @user
    else
      render 'edit'
    end
  end

能力等级:

class Ability
  include CanCan::Ability
  def initialize(user)
    user ||= User.new

    can :read, :all
    can :create, User
    can :create, Group

    can :update, User, id: user.id
  end
end

如果我更改authorize_resourceload_and_authorize_resource然后它按预期工作。但这不应该是相关的,当然?

4

4 回答 4

1

关于为什么会发生这种情况,我(还)没有答案,但我遇到了基本相同的问题。我的情况不同之处在于手动授权每个操作(而不是依赖“授权资源”或“load_and_authorize”是关键。

于 2013-01-24T07:56:05.463 回答
1

您的代码仅授权用户访问编辑和更新操作而不是@user对象

您必须像这样手动授权对象

尝试这个,

def edit
  @user = User.find(params[:id])
  authorize! :update, @user
end

def update
  @user = User.find(params[:id])
  authorize! :update, @user
  if @user.update_attributes(params[:user])
   redirect_to @user
  else
   render 'edit'
  end
end
于 2012-10-12T14:17:45.077 回答
1

我和你一样面临同样的问题,但对我来说,我正在使用带有 cancan 的设计。因此,在我的控制器中,我会放

 before_filter :authenticate_user!, :except=>[:create]

它将验证除创建之外的用户。

def index
    @user = User.all
    authorize! :index, @user
    respond_to do |format|
       format.html # index.html.erb
       format.xml  { render :xml => @user }
    end
end

您想要授权用户访问的每个控制器功能,您都可以这样做,似乎您必须通过将每一个功能放入您需要授权的功能而不是使用 load_and_authorize_resource 来做很多工作,但希望可以从我完成的事情中帮助你。这里是资源:https://github.com/ryanb/cancan/wiki/authorizing-controller-actions。如果您得到答案以及为什么 load_and_authorize_resource 不起作用,请也发布到这里 :)

于 2012-10-12T15:01:42.793 回答
1

我也遇到了这个问题,这就是我发现的。

如果我正确阅读源代码,则在:update操作期间load_and_authorize执行find_by加载资源,然后调用authorize!它。但是,在应用传入参数后,我看不到它在哪里授权。(如果我读错了,请有人纠正我。)

我看到的用例是有人编辑资源,并在编辑中更新资源中的值,使其不再有资格在保存时通过授权。(当然,我正在设置 UI 来帮助避免这种情况,但显然我仍然想保护资源。)运行功能测试,我能够设置我希望不会通过控制器:update操作授权的属性,大概是因为检查发生在解析属性之前。

到目前为止,我解决它的方法是authorize!在设置属性后再次调用,这意味着我不能使用update_attributes,因为我想在保存之前进行授权:

class FooController < ApplicationControlller

  load_and_authorize_resource

  def update

    # slurp the mass assignable params
    @foo.attributes = params[:foo]

    # set some other params
    @foo.some_other_attr = 'bar'

    # authorize again, now that we have updated the params
    authorize! :update, @foo

    if @foo.save!
      flash[:notice] = I18n.t(...)   
      respond_with(@foo)
    # ...
    end 
  end 
end

另一种方法是创建一个 before_filter,@foo自己加载实例,然后像上面那样调用授权,但这并没有真正让事情变得更干净,恕我直言。它只会节省一个授权!称呼。

我很好奇其他人是如何处理这个问题的。我对 CanCan 相当陌生,所以我假设我做错了什么。:)

于 2013-05-10T04:17:08.410 回答