rails:与belongs_to关系的大规模分配安全问题

Posted

技术标签:

【中文标题】rails:与belongs_to关系的大规模分配安全问题【英文标题】:rails: mass-assignment security concern with belongs_to relationships 【发布时间】:2011-01-10 16:09:12 【问题描述】:

我一直在阅读有关 Rails 安全问题的信息,其中让我最担心的是批量分配。我的应用程序正在使用 attr_accessible,但是我不确定我是否完全知道处理暴露关系的最佳方法是什么。假设我们有一个基本的内容创建/所有权网站。用户可以创建博客文章,并拥有一个与该博客文章相关联的类别。

所以我有三个模型:

用户 帖子:属于一个用户和一个类别 类别:属于用户

我允许对 category_id 进行批量分配,因此用户可以将其取消,将其更改为他们的类别之一,或者通过批量分配,我想他们可以将其更改为其他人的类别。这就是我有点不确定最好的方法是什么。

我调查的资源(特别是 railscast #178 和该 railscast 提供的 resource)都提到该关联不应该是可批量分配的,这是有道理的。我只是不确定如何让用户更改 postcategory 内容。

关于如何最好地解决这个问题的任何想法?我看错了吗?

更新:希望能进一步澄清我的担忧。

假设我在 Post,我是否需要类似以下内容:

def create
  @post = Post.new(params[:category])

  @post.user_id = current_user.id

  # CHECK HERE IF REQUESTED CATEGORY_ID IS OWNED BY USER

  # continue on as normal here
end

这似乎是很多工作?我需要在更新和创建操作中检查每个控制器。请记住,不仅仅是一个 belongs_to 关系。

【问题讨论】:

【参考方案1】:

我想,您的用户可以通过某种编辑表单来更改它。

基于此,Mass Assignment 确实适用于那些试图通过 curl 之类的东西弄乱您的应用程序的邪恶类型。我称他们为卷发小子。

这就是说,如果您使用attr_protected -(此处放置您不希望他们更改的字段)或孩子最喜欢的attr_accessible(可以更改的字段)。

您会听到两者的论据,但如果您在模型中使用 attr_protected :user_id,然后在 CategoryController#create 操作中,您可以执行类似的操作

def create
  @category = Category.new(params[:category])

  @category.user_id = current_user.id
  respond_to do |format|
....#continue on as normal here
end

【讨论】:

谢谢@pjammer。我对上面的例子特别感兴趣。你写的是正确的,但我对从 Post 到 Category 的 belongs_to 更感兴趣。对于 Post 和 Category 上的 current_user,我已经有了类似的东西(虽然我在模型中有)。【参考方案2】:

好的,所以搜索了一下,最后想出了一些对我有用的东西。我喜欢尽可能将逻辑排除在控制器之外,因此此解决方案是基于模型的解决方案:

# Post.rb
validates_each :asset_category_id do |record, attr, value|
  self.validates_associated_permission(record, attr, value)
end

# This can obviously be put in a base class/utility class of some sort.
def self.validates_associated_permission(record, attr, value)
  return if value.blank?
  class_string = attr.to_s.gsub(/_id$/, '')
  klass = class_string.camelize.constantize

  # Check here that the associated record is the users
  # I'm leaving this part as pseudo code as everyone's auth code is
  # unique.
  if klass.find_by_id(value).can_write(current_user)
    record.errors.add attr, 'cannot be found.'
  end
end

我还发现 rails 3.0 将有一个更好的方法来指定这个而不是超通用 validates_each 所需的 3 行。

http://ryandaigle.com/articles/2009/8/11/what-s-new-in-edge-rails-independent-model-validators

【讨论】:

其他答案非常有帮助,但这实际上解决了我的问题,因此我接受了。

以上是关于rails:与belongs_to关系的大规模分配安全问题的主要内容,如果未能解决你的问题,请参考以下文章

在 Rails 中通过其 belongs_to 关系查询记录

Rails 查询具有 has_many 和 belongs_to 关系的模型

如何更新脚手架生成的 MVC + 路由,用于在 Rails 中具有 2 个 belongs_to 关系的嵌套资源

Rails ActiveRecord - 获取与锁定的belongs_to关联

以编程方式获取 Rails 4 中的 belongs_to 关联的类

Rails 5:将belongs_to关联与自定义名称添加到模型和迁移