默认情况下,ActiveRecord中的.order方法参数是否已清理?

时间:2013-02-15 14:50:35

标签: ruby-on-rails rails-activerecord

我正在尝试将字符串传递给.order方法,例如

Item.order(orderBy)

我想知道orderBy是否会默认清理,如果没有,那么最好的清理方法是什么。

5 个答案:

答案 0 :(得分:16)

订单没有消毒。此查询实际上将删除Users表:

Post.order("title; drop table users;")

如果orderBy有任何方式可能会被用户输入污染,那么您需要在运行查询之前检查orderBy变量。这样的事情可以奏效:

items = Item.scoped
if Item.column_names.include?(orderBy)
  items = items.order(orderBy)
end

答案 1 :(得分:6)

它们的清理方式与使用.where的{​​{1}}子句相同,但您可以使用?

#sanitize_sql_for_order

http://api.rubyonrails.org/classes/ActiveRecord/Sanitization/ClassMethods.html#method-i-sanitize_sql_for_order

答案 2 :(得分:2)

我使用以下内容:

@scoped = @scoped.order Entity.send(:sanitize_sql, "#{@c} #{@d}")

其中实体是模型类。

答案 3 :(得分:0)

使用ActiveRecord::Relation扩展sanitized_order

考虑Dylan's lead我决定扩展ActiveRecord::Relation以添加一个可链接的方法,该方法将自动清理传递给它的order参数。

以下是您的称呼方式:

Item.sanitized_order( params[:order_by], params[:order_direction] )

以下是扩展ActiveRecord::Relation以添加它的方式:

<强>配置/初始化/ sanitized_order.rb

class ActiveRecord::Relation

  # This will sanitize the column and direction of the order. 
  # Should always be used when taking these params from GET.
  #
  def sanitized_order( column, direction = nil )
    direction ||= "ASC"

    raise "Column value of #{column} not permitted."       unless self.klass.column_names.include?( column.to_s ) 
    raise "Direction value of #{direction} not permitted." unless [ "ASC", "DESC" ].include?( direction.upcase ) 

    self.order( "#{column} #{direction}" )
  end

end

它主要做两件事:

  1. 它确保column参数是klass的基础ActiveRecord::Relation的列名称。

    在上面的示例中,它会确保params[:order_by]Item列之一。

  2. 确保方向值为“ASC”或“DESC”。

  3. 可以采取进一步措施,但我发现在接受用户排序参数时,易用性和干燥性在实践中非常有用。

答案 4 :(得分:0)

仅针对Rails 5+进行更新,在撰写本文时,将数组传递到order将(试图)清除右侧输入:

Item.order(['?', "'; DROP TABLE items;--"])
#=> SELECT * FROM items ORDER BY '''; DROP TABLE items;--'

这将在Rails 5.1中触发关于“危险查询方法”的过时警告,该警告将在Rails 6中被禁止。如果您知道左手输入是安全的,则将其包装在Arel.sql调用中将使警告,并且大概在Rails 6中仍然有效。

Item.order([Arel.sql('?'), "'; DROP TABLE items;--"])
#=> SELECT * FROM items ORDER BY '''; DROP TABLE items;--'

重要的是要注意,左侧的不安全SQL将未经修改地发送到数据库。小心!

如果您知道输入将成为模型的属性,则可以将参数作为哈希值传递:

Item.order(column_name => sort_direction)

在这种形式下,如果列名对模型无效或排序方向无效,ActiveRecord将会进行投诉。