Rails:与belongs_to关系有关的批量分配安全问题

发布于 2024-08-19 09:09:38 字数 1152 浏览 2 评论 0 原文

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

所以我有三个模型:

  • user
  • post: 属于用户和类别
  • category: 属于用户

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

我调查过的资源(特别是 railscast #178资源是由该railscast提供的) ,都提到关联不应该是可批量分配的,这是有道理的。我只是不确定如何允许用户以 Railsy 方式更改帖子类别

关于如何最好地解决这个问题有什么想法吗?我是否以错误的方式看待它?

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

假设我在 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”关系。

I've been reading up on rails security concerns and the one that makes me the most concerned is mass assignment. My application is making use of attr_accessible, however I'm not sure if I quite know what the best way to handle the exposed relationships is. Let's assume that we have a basic content creation/ownership website. A user can have create blog posts, and have one category associated with that blog post.

So I have three models:

  • user
  • post: belongs to a user and a category
  • category: belongs to user

I allow mass-assignment on the category_id, so the user could nil it out, change it to one of their categories, or through mass-assignment, I suppose they could change it to someone else's category. That is where I'm kind of unsure about what the best way to proceed would be.

The resources I have investigated (particularly railscast #178 and a resource that was provided from that railscast), both mention that the association should not be mass-assignable, which makes sense. I'm just not sure how else to allow the user to change what the category of the post would be in a railsy way.

Any ideas on how best to solve this? Am I looking at it the wrong way?

UPDATE: Hopefully clarifying my concern a bit more.

Let's say I'm in Post, do I need something like the following:

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

That seems like a lot of work? I would need to check that on every controller in both the update and create action. Keep in mind that there is more than just one belongs_to relationship.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

野鹿林 2024-08-26 09:09:38

我认为您的用户可以通过某种编辑形式来更改它。

基于此,批量分配实际上适用于那些试图通过诸如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

Your user can change it through an edit form of some kind, i presume.

Based on that, Mass Assignment is really for nefarious types who seek to mess with your app through things like curl. I call them curl kiddies.

All that to say, if you use attr_protected - (here you put the fields you Do Not want them to change) or the kid's favourite attr_accessible(the fields that are OK to change).

You'll hear arguments for both, but if you use attr_protected :user_id in your model, and then in your CategoryController#create action you can do something like

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

  @category.user_id = current_user.id
  respond_to do |format|
....#continue on as normal here
end
得不到的就毁灭 2024-08-26 09:09:38

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

# 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

OK, so searched around a bit, and finally came up with something workable for me. I like keeping logic out of the controllers where possible, so this solution is a model-based solution:

# 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

I also found that rails 3.0 will have a better way to specify this instead of the 3 lines required for the ultra generic validates_each.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文