15

可能在这里做一些愚蠢的事情,但这是我的基本千篇一律的类:

class League < ActiveRecord::Base

    private
      def league_params
        params.require(:full_name).permit!
      end

end

在创建 League 的新实例时:

2.0.0-p0 :001 > l = League.new(full_name: 'foo', short_name: 'bar')
WARNING: Can't mass-assign protected attributes for League: full_name, short_name

我在这里到底做错了什么?这是 Rails 4.0.0.beta1 构建 + Ruby 2.0

** 更新 **

我现在意识到强参数现在在控制器中而不是在模型中强制执行。原来的问题仍然存在。如果在控制器级别允许它们,如果我在 Rails 控制台中创建实例,如何正确地将属性列入白名单?我不需要attr_accessible在这种情况下也使用,从而完全复制试图“修复”的强参数吗?

4

4 回答 4

14

两件事情。league_params定义在控制器中,而不是模型中。并且params.require()应该包含需要出现在参数中的模型的名称,而不是属性。属性存在检查仍应在模型验证中。并且在使用permit!. 所以,它应该是这样的:

class LeaguesController < ApplicationController

  private
    def league_params
      params.require(:league).permit!
    end

end

更新:

是的,如果您希望在直接访问模型时限制属性,则需要切换回attr_accessible在模型中使用。该功能已移至此 gem:https ://github.com/rails/protected_attributes 。

我认为假设如果您直接在控制台中使用模型,则不需要保护属性,因为您确切知道输入的内容。由于控制台可以完全访问您的应用程序,因此管理整个数据库就像恶意分配属性一样容易。

于 2013-04-11T23:45:50.083 回答
7

强参数attr_accessible都存在的基本安全原因是模型中的某些属性不应被允许更改,除非它是您的代码的明确意图。

他们之间的细微差别是他们工作的透视形式。

StrongParameters专注于用例:考虑到任何条件,每个控制器的操作都可以微调以允许或禁止某些参数。完全的灵活性。

attr_accessible采取不同的观点。它不是专注于用例,而是专注于角色。例如,根据用户的角色,某些属性可以更改或不更改。


使用StrongParameters的方法是在参数哈希上应用requireandpermit关键字。

require声明一个键必须存在于 params 散列中。require如果没有这样的密钥,将引发异常。

permit声明一个字段是允许的。任何不允许的键都将从散列中删除,因此不会通过批量分配的方式传递给模型。

模型

class League
   attr_protected :final_price  # Nobody can mass-assign the final price
   attr_accessible :winner_name, :as => :jury
end

和控制器

class LeaguesController < ApplicationController

这两个动作使用StrongParameters

  # A common user can create a league
  def create
    league = League.new(league_params)
    league.final_price = 1000
    league.save
    redirect_to(league)
  end

  # But only the admin can publish a league
  def publish_league
     league = League.find(params[:id]
     league.update_attributes(league_params_as_admin)
  end

这个使用attr_accessible

  def publish_the_winner
    league = League.find(params[:id]
    # We would expect the current_user.role to return :jury.
    league.assign_attributes(params[:league], :as => current_user.role)
  end

  private
    def league_params
      params.require(:league).permit(:name)
    end

    def league_params_as_admin
      params.require(:league).permit(:name, :status)
    end 

end

在我的经验中:

使用强参数的灵活性来微调可以在每个控制器中批量分配的属性。

使用 attr_accesible 的无所不在确保某些属性无论如何都不能被大量分配。例如,在 Resque 任务中,您可以将用户输入作为参数传递。您将使用 attr_accesible 检查某些属性是否未批量分配。

更多信息:

http://api.rubyonrails.org/classes/ActiveModel/MassAssignmentSecurity/ClassMethods.html

https://github.com/rails/strong_parameters

于 2013-04-14T00:05:55.433 回答
1

即使您正在运行 Rails 4,白名单似乎也处于活动状态。您是否从 Rails 3 应用程序升级到 Rails 4?你有这个config/application.rb吗?

config.active_record.whitelist_attributes = true

仔细检查所有模型上的强参数是否有效。如果是,您可以将此设置更改为false

另外,请仔细检查您的模型中是否没有attr_accessible

于 2013-04-19T05:43:50.150 回答
0

如果您直接调用模型,那么是的,它将回避您在控制器中实现的任何逻辑。

但是,您可以从控制台调用您的控制器,然后在那里实现的 StrongParameters 将生效。

请参阅如何从 Rails 的控制台调用控制器/视图方法?

于 2013-04-15T23:10:44.910 回答