简体   繁体   English

声明强参数中的值不能是数组或单一标量类型

[英]Declare that the value in strong params must NOT be an array or of a one scalar type

Application accepts a GET request to index products and accepts page param (which should be an integer).应用程序接受 GET 请求以索引产品并接受page参数(应该是整数)。

eg http://localhost/products?page=2例如http://localhost/products?page=2

Is there a way to ensure that it really is an integer?有没有办法确保它真的是 integer?

Or actually the problem is: Is there a way to ensure that it is NOT an array?或者实际上问题是:有没有办法确保它不是数组?

eg http://localhost/products?page[]=2 or http://localhost/products?page[random_key]=2例如http://localhost/products?page[]=2http://localhost/products?page[random_key]=2

This will result in an error somewhere in the code.这将导致代码某处出错。

Now, I know that there is a way to declare it should be an array or a json:现在,我知道有一种方法可以声明它应该是一个数组或一个 json:

To declare that the value in params must be an array of permitted scalar values, map the key to an empty array:要声明 params 中的值必须是允许标量值的数组,map 是空数组的键:

params.permit(id: [])

And the easiest method I can think of is literally to test if it is NOT an array:我能想到的最简单的方法就是直接测试它是否不是数组:

run_the_code unless params[:page].is_a?(Array)
# or
run_the_code if params[:page].is_a?(Integer)

But isn't there a simpler way to use ActionParameters API for example?但是没有更简单的方法来使用 ActionParameters API 吗?

eg例如

params.permit(page: :integer)

The strong parameters API is really only designed to do one thing - slice the parameters down to a whitelist to avoid mass assignment vulnerabilities where a malicous user manages to assign properties they should not have been able to assign.强参数 API 实际上只设计用于做一件事——将参数切分到白名单,以避免恶意用户设法分配他们不应该分配的属性的大规模分配漏洞。 It's not concerned with validating the presence or type of the parameters.它不关心验证参数的存在或类型。 That's not its job.那不是它的工作。

You don't have to worry about it being an array if you just use .permit(:page) since the permitted scalar types doesn't include hashes or arrays. But this really has more to with preventing exploits where a setter method could accept a hash then validating the type of the parameters.如果您只使用.permit(:page) ,则不必担心它是一个数组,因为允许的标量类型不包括哈希或 arrays。但这实际上更多地用于防止 setter 方法可以接受的漏洞利用a hash 然后验证参数的类型。

There is also the small fact that formdata pairs (both in the query and request body) are not typed - its all just strings and its really just the backend that converts the parameters into its expected types.还有一个小事实,即表单数据对(在查询和请求正文中)都没有类型化——它只是字符串,实际上只是将参数转换为预期类型的后端。 params[:page].is_a?(Integer) will thus always be false. params[:page].is_a?(Integer)因此将始终为假。 Beyond parsing out hashes and arrays Rack doesn't actually have any built in type hinting like for example ?page(i)=2 like you'll find in some frameworks.除了解析哈希和 arrays Rack 实际上没有任何内置类型提示,例如?page(i)=2就像您在某些框架中会发现的那样。

Typically in Rails the model handles typecasting the user input and providing validations.通常在 Rails 中,model 处理用户输入的类型转换并提供验证。

# this is ridiculously overkill
class Paginator
  include ActiveModel::Model
  include ActiveModel::Attributes
  attribute :page, :integer
  attribute :per_page, :integer
  validates :page, numericality: { only_integer: true }
  validates :per_page, numericality: { only_integer: true }

  def to_query
    attributes.symbolize_keys.compact_blank
  end
end
paginator = Paginator.new(params.permit(:page, :per_page))
if paginator.valid?
  Othermodel.paginate(**paginator.to_query)
end

However there are gems that provide alternative approaches such as dry-validations or you can just simply write a method which rejects the parameter if it cannot be coerced into a non-zero integer.然而,有些 gem 提供替代方法,例如干式验证,或者您可以简单地编写一个方法,如果不能将参数强制转换为非零值 integer 则拒绝该参数。

private 

def page
  params.permit(:page).to_i.then{ |n| n.zero? ? nil : n }
end 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM