gpt4 book ai didi

ruby-on-rails - 使用 declarative_authorization 保护敏感属性

转载 作者:数据小太阳 更新时间:2023-10-29 06:33:32 25 4
gpt4 key购买 nike

使用 declarative_authorization 按角色保护属性的好方法是什么? ?例如,用户可以编辑他的联系信息,但不能编辑他的角色。

我的第一个想法是为不同的场景创建多个 Controller 操作。我很快意识到随着 protected 属性数量的增加,这会变得多么笨拙。为用户角色执行此操作是一回事,但我可以想象多个 protected 属性。添加很多 Controller 操作和路由感觉不对。

我的第二个倾向是围绕特定的敏感属性创建权限,然后使用 declarative_authorizations 提供的 View hepers 包装表单元素。但是,在我看来,模型和 Controller 这方面有点模糊。建议会很棒。

请建议使用 declarative_authorizations 按角色保护属性的最佳方法。

最佳答案

编辑 2011-05-22
从 3.1RC 开始,Rails 中现在有类似的东西 https://github.com/rails/rails/blob/master/activerecord/test/cases/mass_assignment_security_test.rb所以我建议现在就走那条路。

原始答案
我只需要将我以前使用的内容移植到 Rails 3。我从来没有专门使用过声明式授权,但这非常简单明了,您应该能够适应它。

添加了 Rails 3 mass_assignment_authorizer ,这让这一切变得非常简单。我以该链接教程为基础,通过类继承和将属性分组到角色中,使其更适合我的领域模型。

在模型中

acts_as_accessible :admin => :all, :moderator => [:is_spam, :is_featured]
attr_accessible :title, :body # :admin, :moderator, and anyone else can set these

在 Controller 中

post.accessed_by(current_user.roles.collect(&:code)) # or however yours works
post.attributes = params[:post]

lib/active_record/acts_as_accessible.rb

# A way to have different attr_accessible attributes based on a Role
# @see ActsAsAccessible::ActMethods#acts_as_accessible
module ActiveRecord
module ActsAsAccessible
module ActMethods
# In model
# acts_as_accessible :admin => :all, :moderator => [:is_spam]
# attr_accessible :title, :body
#
# In controller
# post.accessed_by(current_user.roles.collect(&:code))
# post.attributes = params[:post]
#
# Warning: This frequently wouldn't be the concern of the model where this is declared in,
# but it is so much more useful to have it in there with the attr_accessible declaration.
# OHWELL.
#
# @param [Hash] roles Hash of { :role => [:attr, :attr] }
# @see acts_as_accessible_attributes
def acts_as_accessible(*roles)
roles_attributes_hash = Hash.new {|h,k| h[k] ||= [] }
roles_attributes_hash = roles_attributes_hash.merge(roles.extract_options!).symbolize_keys

if !self.respond_to? :acts_as_accessible_attributes
attr_accessible
write_inheritable_attribute :acts_as_accessible_attributes, roles_attributes_hash.symbolize_keys
class_inheritable_reader :acts_as_accessible_attributes

# extend ClassMethods unless (class << self; included_modules; end).include?(ClassMethods)
include InstanceMethods unless included_modules.include?(InstanceMethods)
else # subclass
new_acts_as_accessible_attributes = self.acts_as_accessible_attributes.dup
roles_attributes_hash.each do |role,attrs|
new_acts_as_accessible_attributes[role] += attrs
end
write_inheritable_attribute :acts_as_accessible_attributes, new_acts_as_accessible_attributes.symbolize_keys
end
end
end

module InstanceMethods
# @param [Array, NilClass] roles Array of Roles or nil to reset
# @return [Array, NilClass]
def accessed_by(*roles)
if roles.any?
case roles.first
when NilClass
@accessed_by = nil
when Array
@accessed_by = roles.first.flatten.collect(&:to_sym)
else
@accessed_by = roles.flatten.flatten.collect(&:to_sym)
end
end
@accessed_by
end

private
# This is what really does the work in attr_accessible/attr_protected.
# This override adds the acts_as_accessible_attributes for the current accessed_by roles.
# @see http://asciicasts.com/episodes/237-dynamic-attr-accessible
def mass_assignment_authorizer
attrs = []
if self.accessed_by
self.accessed_by.each do |role|
if self.acts_as_accessible_attributes.include? role
if self.acts_as_accessible_attributes[role] == :all
return self.class.protected_attributes
else
attrs += self.acts_as_accessible_attributes[role]
end
end
end
end
super + attrs
end
end
end
end

ActiveRecord::Base.send(:extend, ActiveRecord::ActsAsAccessible::ActMethods)

spec/lib/active_record/acts_as_accessible.rb

require 'spec_helper'

class TestActsAsAccessible
include ActiveModel::MassAssignmentSecurity
extend ActiveRecord::ActsAsAccessible::ActMethods
attr_accessor :foo, :bar, :baz, :qux
acts_as_accessible :dude => [:bar], :bra => [:baz, :qux], :admin => :all
attr_accessible :foo
def attributes=(values)
sanitize_for_mass_assignment(values).each do |k, v|
send("#{k}=", v)
end
end
end

describe TestActsAsAccessible do
it "should still allow mass assignment to accessible attributes by default" do
subject.attributes = {:foo => 'fooo'}
subject.foo.should == 'fooo'
end
it "should not allow mass assignment to non-accessible attributes by default" do
subject.attributes = {:bar => 'baaar'}
subject.bar.should be_nil
end
it "should allow mass assignment to acts_as_accessible attributes when passed appropriate accessed_by" do
subject.accessed_by :dude
subject.attributes = {:bar => 'baaar'}
subject.bar.should == 'baaar'
end
it "should allow mass assignment to multiple acts_as_accessible attributes when passed appropriate accessed_by" do
subject.accessed_by :bra
subject.attributes = {:baz => 'baaaz', :qux => 'quuux'}
subject.baz.should == 'baaaz'
subject.qux.should == 'quuux'
end
it "should allow multiple accessed_by to be specified" do
subject.accessed_by :dude, :bra
subject.attributes = {:bar => 'baaar', :baz => 'baaaz', :qux => 'quuux'}
subject.bar.should == 'baaar'
subject.baz.should == 'baaaz'
subject.qux.should == 'quuux'
end
it "should allow :all access" do
subject.accessed_by :admin
subject.attributes = {:bar => 'baaar', :baz => 'baaaz', :qux => 'quuux'}
subject.bar.should == 'baaar'
subject.baz.should == 'baaaz'
subject.qux.should == 'quuux'
end
end

关于ruby-on-rails - 使用 declarative_authorization 保护敏感属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5269333/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com