为什么切割params散列会对质量分配造成安全问题?

通过批量分配来防止安全风险的官方方法是使用attr_accessible 。 但是,一些程序员认为这不是模型的工作(或者至少不仅仅是模型的工作)。 在控制器中执行此操作的最简单方法是切割params哈希:

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

但是文档说明:

请注意,使用Hash#except或Hash#slice代替attr_accessible来清理属性将无法提供足够的保护。

这是为什么? 为什么白名单切片的params不能提供足够的保护?

更新: Rails 4.0将发布强参数 ,一个精细的参数切片,所以我猜整个切片的事情毕竟不是那么糟糕。

切片和控制器除外的问题可能与模型中的accept_nested_attributes_for结合使用。 如果使用嵌套属性,则需要在所有位置切片参数,在控制器中更新它们,这并不总是最简单的任务,尤其是对于深度嵌套的方案。 使用attr_accesible你没有这个问题。

从Rails 4开始,切片参数将是处理质量分配安全性的首选方法。 Rails核心团队已经开发了一个插件来处理这个问题,他们正在努力集成对嵌套属性和签名表单的支持。 绝对值得一看: http : //weblog.rubyonrails.org/2012/3/21/strong-parameters/

来自DHH的有趣的要点是控制器切换与单独白名单:

https://gist.github.com/1975644

 class PostsController < ActionController::Base def create Post.create(post_params) end def update Post.find(params[:id]).update_attributes!(post_params) end private def post_params params[:post].slice(:title, :content) end end 

注释强化了在控制器中管理它的需要:

https://gist.github.com/1975644#gistcomment-88369

我个人同时应用两者 - attr_accessible与切片,以确保没有任何意外的通过。 永远不要单靠黑名单!

只是从params哈希中删除:name可以防止为该操作设置该属性。 它仅适用于您记得保护的操作。

但是,这种做法并不能保护您免受使用为关联自动添加的所有方法的滥用。

 class User < ActiveRecord::Base has_many :comments end 

即使从params中删除comments_ids属性,也会让设置comments_ids属性的人容易受到攻击。

由于为关联添加了很多方法,并且由于它们将来可能会发生变化,因此最佳做法是使用attr_accessible保护模型上的属性。 这将最有效地阻止这种攻击。

@tokland你的最后评论在某种程度上是不正确的。 除非您的网站将浏览器作为数据进入和退出的唯一入口点。

如果您的webapp具有API或与控制器级别的其他API保护通信,则会在其后面留下漏洞,并且不会清理或检查来自其他来源的所有数据。 我建议保持原样,在application.rb中启用大量分配保护,并推动ActiveSupport FormHelpers像Django / Python一样工作。