rails 数据表单的保护:attr_accessor, attr_accessible and attr_protected

attr_accessor是Ruby语言的内置方法,此方法是为变量自动生成get set方法,从而可以省去一堆重复的get set方法。

 

attr_accessible和attr_protected是rails框架提供的方法,使用的场景是如下的情况:

 

收到表单,传统的方式是这样的:

user = User.new
user.user_name = params["user[user_name]"]
user.password = params["user[password]"]

这个代码违法了DRY原则,所以rails支持用下面的方式来快速创建对象:

user = User.new params[:user]

通过CoC,此时会自动把params中的user_name和password赋值给user对象的对应属性。这样,不管user有多少个属性,只需要一行代码就搞定。

 

user = User.new params[:user],这种赋值方式,rails这帮guy就骑了个名字叫做  mass assignment

 

但是这个同时带来另外一个问题,User的某些属性不希望通过浏览器的方式(有可能是通过手动编写的程序提交表单,而不是通过浏览器的form)来修改,比如:user.is_admin,这样如果有人恶意通过程序来调用此接口,就会出现安全漏洞,把自己升级为管理员。

 

为了避免这样的情况,rails提供了两个方法(attr_accessible和attr_protected),用来限制哪些属性可以通过这种方式更新,哪些属性不能这样。

attr_accessible相当于是白名单,定义哪些属性可以被mass assignment(大量赋值)

attr_protected相当于是黑名单,定义哪些属性不可以被mass assignment

 

 

Mass assignemet是個Rails專屬,因為太方便而造成的安全性議題。ActiveRecord物件在新建或修改時,可以直接傳入一個Hash來設定屬性(這功能叫做Mass assignment):

def create

  params[:user] #=> {:name => “ow3ned”, :is_admin => true}

  @user = User.create(params[:user])

end



def update

  @user = User.update_attributes(params[:user])

end

但是如果這個Model包含一些敏感屬性,例如此例中is_admin是個辨別是否是管理員的Boolean值,它不應該讓使用者可以修改。這時候我們就必須用attr_protectedattr_accessible方法來保護這些屬性:

class User < ActiveRecord::Base

  attr_protected :is_admin

end

使用attr_protected是黑名單,在Mass assignment時就會略過這個is_admin這個屬性。或是使用attr_accessible則是白名單,在Mass assignment時只會設定這些屬性:

class User < ActiveRecord::Base

  attr_accessible :name

end    

這些被保護的屬性如果要給值,你就必須手動來了,而且通常會在不同的Controller,例如只會出現在後台管理中:

params[:user] #=> {:name => "ow3ned", :is_admin => true}

@user = User.new(params[:user])

@user.is_admin #=> false # not mass-assigned

@user.is_admin = true

@user.is_admin #=> true
 

 

你可能感兴趣的:(protected)