rails4 使用 Strong Parameters 机制,避免非法的参数进入到应用中
post_params = {:title => "post", :body => "post body"}
Post.create(post_params)
没有进行 permit 可以,也可以创建成功,debug 发现使用 params 创建 post 的时候就会报错
@post = Post.create(params[:post])
ActiveModel::ForbiddenAttributesError
那么这里需要注意的是:使用 hash 和 params 创建对象的不同之处,原理是这样的
params.class
=> ActionController::Parameters
params.class.ancestors
=> ActionController::Parameters, ActiveSupport::HashWithIndifferentAccess, Hash, ...
在创建 ActiveRecord::Base 对象的时候,rails 会检查时候有 permitted?方法,如果没有进行 permit 则会抛出异常
def sanitize_for_mass_assignment(attributes)
if attributes.respond_to?(:permitted?) && !attributes.permitted?
raise ActiveModel::ForbiddenAttributesError
else
attributes
end
end
ActionController::Parameters 提供了 permitted?方法
{:title => "post", :body => "post body"}
def permitted?
...
end
普通 Hash 对象,则没有 permitted?方法
{:title => "post", :body => "post body"}
所以 Strong parameters 是通过 params 来严格控制传进来的参数的,而不是在模型层进行检验, 还是可以通过普通 hash 作为参数进行创建对象
当使用属性值 hash 来创建一个对象的时候,直接调用 permit 即可 但是如何使用 permit 来处理复杂的,甚至嵌套的属性值的,实践证明,可以使用一下这个规则来处理
To Permit a Hash, Pass an Array To Permit an Array, Pass a Hash
##To Permit a Hash, Pass an Array
rails4 需要我们将参数列入到白名单,或者经过我们的允许,才能传递到应用中, 这就是 rails4 比较重要的一个特性:Strong parameters 增强 Controller 层安全机制,有效的避免破坏性的,垃圾性的参数进入到应用中。
下面是它的简单应用,首先告诉 rails 哪些属性对于创建一篇文章是允许的,
def create
post_params =params.require(:post).permit(:title, :body)
@post = Post.new(post_params)
end
#文章的属性属性值hash
Hash: post_params = {:title => "post", :body => "post body"}
#允许的参数值Array
Array: params.permit([:title, :body])
可以看出,我们通过 permit 一个 Array 允许这个 hash 的参数进入到我们的应用中, 这就是 To Permit a Hash, Pass an Array
通过 api 传过来的 json 数据是这样的,我们如何来创建 post 对象呢
parsed_json = {
:title => "post", :body => "post body",
:comments => [
{:content => "comment one"},
{:content => "comment two"}
]
}
params.require(:post).permit(:title, :body, :comments =>[:content])
Array:[{:content => "comment one"},{:content => "comment two"}] Hash: :comments =>[:content] 当我们要传递 comments 内容这个 Array 的时候,我们需要在 permit 函数中指定 Hash, :comments =>[:content] 这就是 To Permit an Array, Pass a Hash
class Post < ActiveRecord::Base
has_many :comments
accepts_nested_attributes_for :comments
end
post_params = params.require(:post).permit(
:title, :body,
:comments_attributes => [:text, :id]
)
@post = Post.create(post_params)
http://patshaughnessy.net/2014/6/16/a-rule-of-thumb-for-strong-parameters