0

嗨,我是 Rails 新手,我想弄清楚如何防止未经授权访问控制器的更新操作。

我知道我可以有一个 before_filer 来踢出没有登录的人redirect_toedit但我想要一种方法来阻止用户编辑不属于他们的对象。

例如:授权用户可以简单地更改job我的应用程序中的对象,方法是直接发送PUT带有 anyjob.id作为参数的请求并更改他们想要的任何字段。

这是我的控制器:

  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 给了我一个错误,说我在一个动作中只能有一个重定向。

4

5 回答 5

2

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

但是,这并不是我真正解决您更大问题的方式。

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

其次,按照您的建议,我会使用 abefore_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

before 过滤器将按顺序执行,因此您在检查权限时已经拥有可用的用户和作业,并且可以检查该特定作业的权限。

于 2013-07-29T22:26:46.263 回答
1
def update
    @job = Job.find(params[:id])

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

    redirect_to jobs_path
end

:)

于 2013-07-29T22:22:48.993 回答
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
于 2013-07-29T22:26:16.310 回答
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
于 2013-07-29T22:23:37.220 回答
0

使用 Else 子句

问题是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
于 2013-07-29T22:26:25.077 回答