Rails:如何防止未经授权访问控制器更新操作

时间:2013-07-29 22:19:33

标签: ruby-on-rails ruby ruby-on-rails-3 model-view-controller

您好我是rails的新手,我正在试图找出如何防止未经授权访问控制器的更新操作。

我知道我可以有一个before_filer,它会启动那些没有登录的人,我在redirect_to操作中有edit但是我想要一种方法来阻止用户编辑一个对象不属于他们。

例如:授权用户只需更改我的应用中的job对象,直接发送PUT个请求job.id作为参数,并更改他们想要的任何字段。< / p>

这是我的控制器:

  def update
    @job = Job.find(params[:id])


    @job.update_attributes(params[:job])
    redirect_to jobs_path
  end

要尝试解决此问题,我尝试检查update操作,如果用户已获得授权,如果他们不是,我会将其重定向到索引页。

  def update
    @job = Job.find(params[:id])

    if @job.user.id != current_login
      redirect_to jobs_path
    end

    @job.update_attributes(params[:job])
    redirect_to jobs_path
  end

但是当我尝试这样做时,rails会给我一个错误,说我在一个动作中只能有一个重定向。

5 个答案:

答案 0 :(得分:2)

嗯,对您当前问题的直接解决方法是使用流量控制来确保在单个请求中只能访问一个redirect_to,正如许多其他人所建议的那样。

然而,这并不是我如何解决你的大问题。

首先,有许多现有的管理授权解决方案,例如cancanrolify。我会调查那些。

其次,我建议您使用before_filter来阻止访问。类似的东西:

before_filter :load_job, :only => [:show, :edit, :update, :delete]
before_filter :require_authorization, :only => [:edit, :update, :delete]

def load_job
  @job = Job.find(params[:id])
end

def require_authorization
  redirect_to jobs_path unless current_user.can_edit?(@job) # or whatever you want to check
end

之前的过滤器将按顺序执行,因此您已经拥有了用户&amp;检查权限时可用的作业,并可以检查该特定作业的权限。

答案 1 :(得分:1)

def update
    @job = Job.find(params[:id])

    @job.update_attributes(params[:job]) unless @job.user.id != current_login

    redirect_to jobs_path
end

:)

答案 2 :(得分:1)

这可能是因为在第一次重定向之后仍然可以执行第二次重定向。 因此,将update_attributes和第二个redirect放入这样的else路径可以解决问题:

    def update
      @job = Job.find(params[:id])

      if @job.user.id != current_login
        redirect_to jobs_path
      else
        @job.update_attributes(params[:job])
        redirect_to jobs_path
      end
    end

答案 3 :(得分:0)

您可以redirect_to jobs_path and returnreturn redirect_to jobs_path

尝试以下方法:

def update
    @job = Job.find(params[:id])

    if @job.user.id != current_login
      redirect_to jobs_path and return
    end

    @job.update_attributes(params[:job])
    redirect_to jobs_path and return
  end

答案 4 :(得分:0)

使用其他条款

问题是redirect_to方法不会结束当前方法;它只是告诉控制器设置一些标题。为了防止出现此问题,您需要确保控件不会“落到”第二个重定向。一种方法是将您的替代路径放入else子句。例如:

def update
  @job = Job.find(params[:id])

  if @job.user.id != current_login
    redirect_to jobs_path
  else
    @job.update_attributes(params[:job])
    redirect_to jobs_path
  end
end