【问题标题】:How can I suppress the assignment of one or more fields in a Ruby-On-Rails mass-assignment?如何禁止在 Ruby-On-Rails 批量分配中分配一个或多个字段?
【发布时间】:2012-07-06 10:44:56
【问题描述】:

我对这个批量分配问题有点困惑。这是我的问题

假设我有一个具有以下属性的用户模型: 姓名 登录 密码 电子邮件

在编辑期间,触发更新方法:

def update
  @user = User.find(params[:id])
  if @user.update_attributes(params[:user]) 
   ....
end

在我看来,保护大多数(如果不是全部)这些属性是有意义的,因为我不希望密码/电子邮件/登录名受到损害。所以我会在模型中这样做

attr_accessible:名称

因此,除了名称之外的所有其他属性都无法批量分配。

如果我这样做,有效的编辑表单将如何工作?是否需要在更新方法@user.email = params[:user][:email]等中一一分配属性?还是我误解了什么(可能)?

谢谢!

编辑:

更具体一点:

通常您会看到带有受保护的 admin 属性的示例。这是有道理的。

但是密码或电子邮件属性呢?这些通常不受保护。为什么密码或电子邮件不受保护?这可能意味着可能有人可以重置电子邮件并重置密码或重置密码属性并获得对系统的访问权限,不是吗?

【问题讨论】:

  • 我编辑了你的标题;希望它能够捕捉到您提出的问题。原来的标题没用。
  • 我不认为这是正确的标题,因为我不是要求那个。我认为这是保护如何工作的普遍问题。我将稍微编辑一下问题以使其更清楚

标签: ruby-on-rails


【解决方案1】:

观看此 railscasts http://railscasts.com/episodes/26-hackers-love-mass-assignment/

您以错误的方式考虑批量分配安全性。 attr_accessbile 不会向公众公开密码值(您将使用 filter_parameter 隐藏该值)。

这样想,你有一个用户表单。您希望用户能够创建一个带有密码的帐户,但您不希望他们能够将自己添加为管理员(他们可以通过 sql 注入或操作 POST 参数来做到这一点)。为了防止这种情况,您可以将 :name、:password、:email 添加到 attr_accessible 并省略 admin 字段。

【讨论】:

  • 我了解管理员示例,但我没有得到密码或电子邮件部分。如果我执行 attr_accessible :email, :login,攻击者可以以这两个形式批量分配吗?我需要以任何方式更改更新方法吗?
  • 它只是说明用户应该能够通过发布请求(很可能是表单)创建或更新哪些属性。
  • 正确。因此,在用户编辑表单中,您可以编辑姓名、电子邮件或密码。我想保护所有这些属性,因为如果不是,我认为这是一个安全漏洞。如果我这样做,我将无法使用 update_attributes(params[:user]) 。我需要一一做 user.email = params[:user][:email], user.name = params[:user][:name] 等等……至少我是这么理解的。但是,对我来说似乎很乱......
  • 如果您保护所有这些,则用户将无法创建帐户。用户需要能够为其电子邮件/用户名设置值并创建密码。
  • 我理解,但这是否意味着用户可以为给定用户批量分配密码?
【解决方案2】:

这个想法是过滤控制器中的参数as described here

class PeopleController < ActionController::Base
  # This will raise an ActiveModel::ForbiddenAttributes exception because it's using mass assignment
  # without an explicit permit step.
  def create
    Person.create(params[:person])
  end

  # This will pass with flying colors as long as there's a person key in the parameters, otherwise
  # it'll raise a ActionController::MissingParameter exception, which will get caught by 
  # ActionController::Base and turned into that 400 Bad Request reply.
  def update
    redirect_to current_account.people.find(params[:id]).tap do |person|
      person.update_attributes!(person_params)
    end
  end

  private
    # Using a private method to encapsulate the permissible parameters is just a good pattern
    # since you'll be able to reuse the same permit list between create and update. Also, you
    # can specialize this method with per-user checking of permissible attributes.
    def person_params
      params.required(:person).permit(:name, :age)
    end
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-03
    • 2011-12-08
    • 2012-07-08
    • 1970-01-01
    • 2012-10-25
    • 2023-02-10
    • 2011-01-08
    • 2014-02-28
    相关资源
    最近更新 更多