作为一名新手ROR开发人员,我一直在考虑保护某些方法的方法,以确保正确的用户正在更新自己的内容。这是我的方法的一个例子。
您会建议采用更清洁的方式或更好的方式来执行此类任务吗?
# Example Controller
class Owner::PropertiesController < Owner::BaseController
def index
end
etc.....
def update
@property = Property.find(params[:id])
# Check correct owner
check_owner(:owner_id => @property.owner_id)
if @property.update_attributes(params[:property])
redirect_to([:owner, @property], :notice => 'Property was successfully updated.')
else
render :action => "edit"
end
end
def destroy
@property = Property.find(params[:id])
# Check correct owner
check_owner(:owner_id => @property.owner_id)
@property.destroy
redirect_to(owner_properties_url)
end
private
def check_owner p = {}
if p[:owner_id] != session[:owner_id]
redirect_to([:owner, @property], :notice => "Property not found.")
end
end
答案 0 :(得分:4)
这是一种做法,虽然IMO有点笨拙。在这些情况下,我倾向于采用以下方法:
class FoosController < ApplicationController
before_filter :find_user
def create
@foo = @user.foos.build
end
def update
@foo = @user.foos.find(params[:id])
end
private
def find_user
@user = User.find(session[:current_user_id])
end
end
它更清晰,意图很明显:您只想尝试找到属于Foo
的{{1}}。这种方法的缺点之一是,如果所有权规则发生变化,就会有一些工作需要改变它,但我发现它对我的合理性很好。
答案 1 :(得分:0)
考虑使用所讨论的技术here。
在您的用户模型中添加关联,并仅通过该关联查询属性。
property = Property.find(params[:id])
# vs
property = current_user.properties.find(params[:id])
答案 2 :(得分:0)
您也可以使用像declarative_authorization这样的宝石来执行此操作。如果你想自己做,我建议你简单地干掉你的代码:
class Owner::PropertiesController < Owner::BaseController
before_filter :check_owner, :only => [:update, :destroy]
def update
if @property.update_attributes(params[:property])
redirect_to([:owner, @property], :notice => 'Property was successfully updated.')
else
render :action => "edit"
end
end
def destroy
@property.destroy
redirect_to(owner_properties_url)
end
private
def check_owner
@property = Property.find(params[:id]
if @property.owner_id != session[:owner_id]
redirect_to([:owner, @property], :notice => "Property not found.") and return
end
end
end
此外,您可以由所有者过滤您的属性,以确保非所有者的用户无法与不属于他/她的属性进行交互。例如:
def update
@owner = Owner.find(session[:owner_id])
@property = @owner.properties.find(params[:id])
redirect_to unauthorized_page and return if @property.nil?
end
这会强制您搜索的属性是属于会话[:owner_id]的属性,而不是整个属性。这意味着会话[:owner_id]不拥有的属性甚至不会被考虑。然后,您可以将此代码放入before_filter中,以便它可以在多个操作中重复使用。