保护方法的良好做法

时间:2011-03-02 00:28:34

标签: ruby-on-rails activerecord

作为一名新手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

3 个答案:

答案 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中,以便它可以在多个操作中重复使用。