您好我是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会给我一个错误,说我在一个动作中只能有一个重定向。
答案 0 :(得分:2)
嗯,对您当前问题的直接解决方法是使用流量控制来确保在单个请求中只能访问一个redirect_to
,正如许多其他人所建议的那样。
然而,这并不是我如何解决你的大问题。
首先,有许多现有的管理授权解决方案,例如cancan或rolify。我会调查那些。
其次,我建议您使用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 return
或return 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