简体   繁体   中英

CanCan not preventing access when it should

Visiting users/1/edit when I'm signed in as different user does not raise an AccessDenied error, and I have no idea why:

  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

Ability class:

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

If I change authorize_resource to load_and_authorize_resource then it works as expected. But this should not be relevant, surely?

Your code only authorize the user to access edit and update action not the @user object

you have to manually authorize the object like this

Try this,

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

I'm facing the same issues like you,but for me,I'm using devise with cancan. Therefore ,in my controller, i will put

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

it will authenticate user except the 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

each of your controller function that you want to authorize the access of user, you can do like this, it seems you have to do lots of works by putting every single in the function that you need to authorize instead just using load_and_authorize_resource, but hope can help ua little from what i have completed. here is the resource:https://github.com/ryanb/cancan/wiki/authorizing-controller-actions. If you get an answer and why the load_and_authorize_resource is not working, post to here too :)

I don't have an answer for you (yet) on why this happens, but I encountered essentially the same issue. My situation was only different in that manually authorizing each action (instead of relying on either "authorize resource" or "load_and_authorize" was the key.

I am running into this issue as well, and here is what I have found.

If I'm reading the source code right , during an :update action, load_and_authorize does a find_by to load the resource, then calls authorize! on it. However, I don't see where it authorizes it after the incoming parameters have been applied. (Someone please correct me if I'm reading this wrong.)

The use case I am seeing this is when someone edits a resource, and in the edit, updates a value in the resource that makes it no longer eligible to pass authorization on save. (Granted, I am setting up the UI to help avoid this situation, but obviously I still want to protect the resource.) Running a functional test, I was able to set attributes that I expected not to pass authorization on the controller :update action, presumably because the check happens before the attributes are parsed.

So far, the way I have worked around it is to call authorize! again after I have set the attributes, which means I can't use update_attributes since I want to authorize before saving:

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

An alternative is to create a before_filter, load the @foo instance yourself, then call authorize as above, but that doesn't really make things much cleaner, IMHO. It would just save on one authorize! call.

I'm curious as to how others are handling this. I am fairly new to CanCan, so I am presuming I am doing something wrong. :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM