【问题标题】:Rails When should I use strong parameters?Rails 什么时候应该使用强参数?
【发布时间】:2021-11-30 20:54:18
【问题描述】:

我不确定我是否正确理解了强参数的概念。我应该对仅用于编辑某些数据的参数使用强参数吗?或者我应该将它们用于我想进入控制器的每个参数?例如我想获取两个日期之间的数据,所以我需要 date1 和 date2 作为参数。我应该在这里使用强参数吗?

【问题讨论】:

  • 强参数用于质量分配,以明确允许(或拒绝)使用较大数据结构中的某些属性。对于单个属性,您可以只使用params[:date1]。 (你在这里很明确)
  • 你能举一些例子来帮助我理解这一点吗?

标签: ruby-on-rails strong-parameters


【解决方案1】:

了解何时应该使用强参数的最简单方法是了解什么是质量分配自愿性。在 Rails 3 中,您可以执行以下操作:

class CreateUsers < ActiveRecord::Migration[3.0]
  def change
    create_table :users do |t|
      t.string :email
      t.string :encrypted_password
      t.boolean :admin
      t.timestamps
    end
  end
end

class UserController < ApplicationController
  def create
    @user = User.new(params[:user])
    if @user.save
      redirect_to @user
    else
      render :new
    end
  end 
end

这里我们只是将“哈希”(它实际上是一个 ActionController::Parameters 实例)直接传递到模型中。恶意用户只需请求:

POST /users?users[admin]=1 

他们已经创建了一个管理员帐户。 In 2012 Egor Homakov famously exploited one such loophole in Github 提交到 Rails 存储库。

使用 cURL 或使用 Web 检查器操作表单来执行这种攻击是微不足道的。

如果我们将用户应该能够传递的属性列入白名单:

class UserController < ApplicationController
  def create
    @user = User.new(
      params.require(:user)
            .permit(:email, :password, :password_confirmation)
    )
    if @user.save
      redirect_to @user
    else
      render :new
    end
  end 
end

那么这就避免了漏洞 - 强参数实际上只是一个简单的 DSL,用于对嵌套散列结构进行切片和切块。 Rail 4 中的变化是,当您将 ActionController::Parameters 的 n 实例传递给模型时,会引发异常,除非在参数对象上调用 #permitted? 返回 true。这避免了由于程序员的懒惰或无知而发生的批量分配漏洞。

它不会以任何其他方式清理您的输入。例如,如果您不小心对待用户输入,它不会阻止 SQL 注入或远程代码执行。

如果您像这个非常人为的示例一样一一传递参数,则不需要强参数:

class UserController < ApplicationController
  def create
    @user = User.new do |u|
      u.email = params[:user][:email]
      u.password = params[:user][:password]
      u.password_confirmation = params[:user][:password_confirmation]
    end
    if @user.save
      redirect_to @user
    else
      render :new
    end
  end 
end

【讨论】:

  • 值得注意的是,您不应该以此处显示的方式真正实现强参数。代码是正确的,但最好在控制器中有一个私有的[MODEL]_params 方法(例如user_paramsarticle_params),您可以从该控制器中需要访问参数的每个方法调用该方法。这样更容易养成使用强参数的习惯 - 很少有理由不使用强参数,当你使用它时你就会知道。
  • @JohnP 该示例是为了简洁而编写的。然而,将你的强参数提取到一个方法中实际上并没有那么多优点,只是它避免了重复。此示例中没有重复,因此不违反 DRY。
  • @JohnP 至于“它使养成习惯更容易”部分 - 这是荒谬的,因为如果你不这样做,rails 会引发异常。
  • @max 谢谢伙计!
  • @max Rails 如果您直接访问params,则不会引发异常。因此,设置私有 user_params 方法或默认设置并始终使用它只是 ISTM 的明智建议 - 您几乎总是会在某些时候访问控制器方法中的参数!当然,在一个简短的例子中,没有重复,但如果我们试图帮助人们,那么建议最佳实践似乎是明智的。 (我无意批评您的回答——正如我所说,这是正确的——只是一种改进。)
猜你喜欢
  • 2010-11-13
  • 2023-04-02
  • 2011-04-15
  • 2017-04-10
  • 2012-03-19
  • 2018-05-12
  • 2018-12-11
  • 1970-01-01
相关资源
最近更新 更多