如何通过动态角色避免质量分配漏洞?

时间:2012-04-29 20:52:21

标签: ruby-on-rails ruby authorization roles mass-assignment

我有用户,帐户和角色模型。角色存储帐户和用户之间的关系类型。

我将attr_accessible留在Role空白以防止批量分配漏洞(否则攻击者可能会更改角色类型 - 所有者,管理员等... - ,帐户或用户ID)。

但是如果管理员想要将订户更改为主持人呢?这会引发质量分配安全例外:

user = User.find(params[:id])
role = user.roles.find_by_account_id(params[:account_id])
role.type = "admin"

我该如何解决这个问题?一种方法是创建一个单独的模型来表示每个角色(所有者,管理员,主持人,订阅者)并使用STI类型模式。这让我做:

user = User.find(params[:id])
user.moderatorship.build(account_id: params([:account_id])

乏味!我必须创建Onwership,Moderatorship,Subscribership等,并让他们继承自Role。如果我想坚持单一的角色模型,我怎样才能拥有动态角色而不让自己暴露于大规模分配漏洞?

加分问题:我应该使用用户has_many角色(用户可以为每种角色类型设置一条记录)还是has_one角色(用户只能有一个角色记录,如果他们的角色必须切换角色变化)模式?

class User < ActiveRecord::Base
  attr_accessible :name, :email
  has_many :accounts, through: roles
end

class Account < ActiveRecord::Base
  attr_accessible :title
  has_many :users, through: roles
end

class Role < ActiveRecord::Base
  attr_accessible
  belongs_to: :user
  belongs_to: :account
end

2 个答案:

答案 0 :(得分:2)

您可以在attr_accessible中使用“as”来拥有不同的分配能力。例如,

attr_accessible :type, as: :admin

然后,当您进行批量作业时,您可以执行类似

的操作
@role.update_attributes {type: :moderator}, as: :admin # Will update type
@role.update_attributes {type: :moderator} # Will not update type

答案 1 :(得分:1)

最灵活的方法是覆盖模型类中的mass_assignment_authorizer方法,以动态更改可访问的属性。

例如:

class Article < ActiveRecord::Base
  attr_accessible :name, :content
  attr_accessor :accessible

  private
  def mass_assignment_authorizer
    super + (accessible || [])
  end
end

现在你可以这样使用它:

@article.accessible = [:important] if admin?

此示例来自RailsCast #237,您可以在其中了解有关此方法的更多信息。


此外,我想向您推荐CanCan gem,它可以帮助您处理角色和能力。