简体   繁体   English

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

[英]Rails: How to prevent unauthorized access of controller update action

Hi I am new to rails and I am trying to figure out how to prevent unauthorized access to the update action of a controller. 嗨,我是Rails的新手,我试图弄清楚如何防止未经授权访问控制器的更新操作。

I know I could have a before_filer that kicks out people that arent logged in and I have redirect_to in the edit action, but I want a way to stop a user from editing an object that does not belong to them. 我知道我可以使用一个before_filer来踢出arent登录的用户,并且在edit操作中具有redirect_to ,但是我想要一种阻止用户编辑不属于他们的对象的方法。

Ex: A authorized user can simply change a job object in my app, by directly sending a PUT request with any job.id as a parameter and change any field they want. 例如:授权用户可以通过直接发送带有任何job.id作为参数的PUT请求并更改他们想要的任何字段来简单地在我的应用程序中更改job对象。

Here is my controller: 这是我的控制器:

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


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

To try and fix this problem I tried to check in the update action if it the user was authorized and if they werent, i would redirect them to the index page. 为了尝试解决此问题,我尝试检查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

But when I try to do this, rails gives me an error saying I can only have one redirect in an action. 但是,当我尝试执行此操作时,Rails给我一个错误,说我只能在一个操作中进行一次重定向。

Well, the straightforward fix to your immediate problem is to use flow control to make sure that only one redirect_to is ever reached on a single request, as many others have suggested. 好了,直接解决您当前问题的方法是使用流控制来确保在单个请求上仅达到一个redirect_to ,就像许多其他建议一样。

However, that's not really how I'd solve your larger problem. 但是,这并不是我要解决的更大问题。

First, there are a lot of existing solutions for managing authorization, such as cancan or rolify . 首先,有许多用于管理授权的现有解决方案,例如cancanrolify I'd look into those. 我会调查一下。

Second, I'd use a before_filter to block access, as you suggest. 其次,正如您所建议的,我将使用before_filter阻止访问。 Something like: 就像是:

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

The before filters will execute in order, so you'll already have the user & the job available when you check permissions, and can check permissions for that specific job. Before筛选器将按顺序执行,因此在检查权限时您已经具有可用的用户和作业,并且可以检查该特定作业的权限。

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

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

    redirect_to jobs_path
end

:) :)

This is probably because after the first redirect the second one could still be executed. 这可能是因为在第一次重定向之后,第二个仍然可以执行。 Thus putting the update_attributes and the second redirect into the else path like this should solve the problem: 因此,像这样将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

You can either do redirect_to jobs_path and return or return redirect_to jobs_path . 您可以执行redirect_to jobs_path and returnreturn redirect_to jobs_path

Try the following: 请尝试以下操作:

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

Use an Else Clause 使用其他条款

The problem is that the redirect_to method doesn't end the current method; 问题是redirect_to方法没有结束当前方法; it just tells the controller to set some headers. 它只是告诉控制器设置一些标题。 In order to prevent this problem, you need to make sure that control doesn't "fall through" to the second redirect. 为了防止出现此问题,您需要确保控件不会“掉线”到第二个重定向。 One way to do this would be to put your alternative path into an else clause. 一种方法是将替代路径放入else子句中。 For example: 例如:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 铁路:确保通往客户的路线安全,以防止未经授权的访问 - RAILS: Securing route to customer to prevent unauthorized access 如何在 Rails 中访问 URL 在 Controller 中显示操作 - How to access URL in Rails Show action in Controller 在Rails控制器测试中,如何访问不同的控制器操作? - In a Rails controller test, how to access a different controller action? 如何在Rails的更新控制器操作中限制外键? - How to restrict foreign keys in Rails' update controller action? Rails API Controller Update Action -- 如何添加多对多 - Rails API Controller Update Action -- How to add many-to-many Rails如何通过Ajax调用返回javascript:更新控制器动作 - Rails how to return javascript via Ajax call in :update controller action 如何删除与父控制器更新操作的关联? 滑轨 - How to delete association with parent controller update action? Rails 如何访问 Rails 5 Action Cable Channels 中的关注点和应用程序控制器代码 - How to access concerns and application controller code in Rails 5 Action Cable Channels 如何在从更新操作呈现编辑操作时阻止rails更改路径 - How to prevent rails from changing the path when the edit action is rendered from update action 没有路线匹配{:action =>“ update”,:controller =>“”-Rails 5 - No route matches {:action=>“update”, :controller=>“” - Rails 5
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM