2011-03-24 47 views
3

我傾向於不需要生產代碼中的mass-assignment功能。 (在我的測試代碼,我用了很多,但在這種情況下我要設置任意列。)Rails安全性:完全避免大規模分配

所以,如果在我的生產代碼,我只是避免這些形式:

Article.new(params[:article]) # or create 
article.attributes = params[:article] 
article.update_attributes(params[:article]) 

,而總是手動枚舉所有的屬性,就像這樣:

Article.new(:title => params[:article][:title], :body => params[:article][:body], ...) 

我是從質量分配安全問題保存(即使不使用attr_accessible/attr_protected)?

編輯:我不只是禁用批量分配的原因是,我希望能寫Article.create!(:blog_id => @blog.id, ...),其中blog_id是一個「unsave」屬性。

回答

10

是,採用第2種方法,你是從用戶分配給其他屬性的安全。

這是一個乾燥的方式寫出來,雖然:

Article.new(params[:article].slice(:title, :body)) 

- 或 -

def article_params 
    params[:article].slice(:title, :body) 
end 

Article.new(article_params) # or create 
article.attributes = article_params 
article.update_attributes(article_params) 
2

config/environments/production.rb末尾添加這樣的:

ActiveRecord::Base.send(:attr_accessible, nil) 
+0

但是我不想這樣做,因爲我希望能夠糾正ite'User.create!(:name =>'J. R. Hacker',:admin => true)'在我的測試代碼中。我的問題是,如果我不全局禁用羣發任務,我還能保存嗎? – 2011-03-24 20:04:28

+2

以上只適用於您的產品代碼,而不是您的測試代碼 – Zabba 2011-03-24 20:05:16

+0

啊,當然是。但問題在於:如果我這樣做,我必須寫'a = Article.new; a.blog_id = blog.id; ...; a.save!'。我寧願寫'Article.create!(blog_id => blog.id,...)' - 但我只能這樣做,如果我離開質量分配打開,即使在不安全的屬性,如blog_id。所以我想知道這是否是一件可以保存的事情(只要我避免傳入被感染的哈希)。 – 2011-03-24 20:11:48

0

我無法獲取多個參數約翰Douthat的方法工作,所以我想出了以下替代方案(取自我的CommentsController):

def set_params 
    @comment.parent_id = params[:blog_comment][:parent_id] 
    @comment.ip_address = request.remote_ip 
    @comment.commentator = current_user.username || "anonymous" 
    @comment.name = params[:blog_comment][:name] 
    @comment.email = params[:blog_comment][:email] 
    @comment.url = params[:blog_comment][:url] 
end 

def create 
    @comment = @post.comments.build(params[:blog_comment]) 
    set_params 

    if @comment.save 
    ... 
end 

def update 
    @comment = Blog::Comment.find(params[:id]) 
    set_params 

    if @comment.update_attributes(params[:blog_comment]) 
    ... 
end