15

通過批量分配防止安全隱患的正式方法是使用attr_accessible。但是,有些程序員覺得這不是模型的工作(或者至少不是模型的只有)。在控制器做的最簡單的方法是切片PARAMS哈希:爲什麼切分params散列會對羣集分配造成安全問題?

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

但是文件指出:

注意,使用Hash#除或哈希#片代替attr_accessible 消毒屬性不會提供足夠的保護。

這是爲什麼? 爲什麼params的白名單切片不能提供足夠的保護?

UPDATE:Rails 4.0 will ship strong-parameters,參數的細化分層,所以我想整個事情切片沒有那麼糟糕。

+1

對於初學者來說,這只是一個不便。使用'attr_accesible',你可以在模型中使用':name'(如果你需要的話),但是如果你把它從'params'散列掉,你就不能這樣做。使用'attr_accesible'也更加語義化,因爲它告訴其他人與模型之間的屬性關係,而對其進行切片則更加神祕。 – Alex

+3

@Alex:我知道* attr_accessible *是一種管理批量分配的便捷方式。好的,但是使用params [:xyz] .slice的安全漏洞是什麼? – tokland

+0

爲了記錄,[attr_accessible](http://api.rubyonrails.org/classes/ActiveModel/MassAssignmentSecurity/ClassMethods.html#method-i-attr_accessible)現在聲明「*請注意,使用Hash#除外或Hash#切片使用attr_accessible來清理屬性基本上提供了相同的功能,但處理嵌套屬性有點棘手。*「另請參見[Edge API](http://edgeapi.rubyonrails.org/classes/ActionController/StrongParameters .html)以獲得先進的Rails 4文檔,並參閱[strong_parameters插件](https://github.com/rails/strong_parameters),瞭解Rails 4之前的使用方法。 – user664833

回答

6

切片和控制器除外的問題可能與模型中的accept_nested_attributes_for結合使用。如果使用嵌套屬性,則需要在所有地方切片參數,在那裏更新控制器中的參數,這並不總是最簡單的任務,特別是對於深度嵌套場景。通過使用attr_accesible,您不會遇到此問題。

+0

啊,嵌套屬性,在這種情況下,過濾'params'確實是個不愉快的工作。 – tokland

2

只需從params散列中刪除:name即可防止爲該操作設置該屬性。它只適用於你記得保護的動作。

但是,這種做法並不能保護您免於濫用使用爲關聯自動添加的所有方法。

class User < ActiveRecord::Base 
    has_many :comments 
end 

將離開你的人設置comments_ids屬性脆弱的,即使你刪除PARAMS的comments屬性。

由於添加了很多關聯方法,並且由於它們將來可能會更改,所以最佳做法是使用attr_accessible保護模型上的屬性。這將最有效地阻止這類攻擊。

+2

Hash#slice用於白名單:{:comments_ids = > [1,2,3],:name =>'hello'}。slice(:name)#=> {:name =>「hello」}。我真的不知道它有什麼可能出錯的地方(危險的短語:-)) – tokland

+1

無論如何,正如我所說的,我明白爲什麼* attr_accessible *是處理大規模分配安全的好方法。但我很好奇切片有什麼問題,額外的安全性提供了什麼* attr_accessible *? – tokland

+2

attr_accessible始終在每一個動作中保護你的模型,而不必記住把它放在每個控制器中。 –

4

從Rails 4開始,切片參數將是處理質量分配安全性的首選方法。 Rails核心團隊已經開發了一個插件來處理這個問題,他們正在集成對嵌套屬性和簽名表單的支持。肯定要檢查的東西:http://weblog.rubyonrails.org/2012/3/21/strong-parameters/

+1

「基本思想是將質量分配保護從模型中移出,並進入控制器所在的位置。」尼斯。 – tokland

0

@tokland您最近的評論是不正確的一些擴展。除非您的網站將瀏覽器作爲數據輸入和輸出的唯一入口點。

如果您的web應用程序具有API或與控制器級別的其他API保護進行通信,並且其後的所有數據都未被清理或檢查。我建議保持原樣,在application.rb中啓用mass-assignment保護,並推進ActiveSupport FormHelpers使其像Django/Python風格一樣工作。

從DHH
+0

我的哪一條評論?我在這個頁面中寫了很多:-)無論如何,我沒有看到在API或瀏覽器表單之間存在差異。當然,重點在於避免用戶通過篡改屬性更新他不應該使用的屬性。 – tokland

+0

@tokland你說的「基本思想是將質量分配保護從模型中移出,並進入控制器所屬的位置。」 – theCrab

+0

這是來自鏈接文章的引用。但我同意,現在我認爲這是*模型和控制器的任務。 – tokland

4

有趣的要點就獨自一人在控制切片VS白名單:

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和slice以確保沒有意外的事情能夠通過。永遠不要依賴黑名單!