我正在尝试将字符串传递给 .order 方法,例如
Item.order(orderBy)
我想知道 orderBy 是否默认被清理,如果没有,清理它的最佳方法是什么。
我正在尝试将字符串传递给 .order 方法,例如
Item.order(orderBy)
我想知道 orderBy 是否默认被清理,如果没有,清理它的最佳方法是什么。
订单未经过消毒。这个查询实际上会删除用户表:
Post.order("title; drop table users;")
如果有任何方式可能被用户输入污染,您需要orderBy
在运行查询之前检查变量。orderBy
像这样的东西可以工作:
items = Item.scoped
if Item.column_names.include?(orderBy)
items = items.order(orderBy)
end
它们的清理方式与带有 的.where
子句不同?
,但您可以使用#sanitize_sql_for_order
:
sanitize_sql_for_order(["field(id, ?)", [1,3,2]])
# => "field(id, 1,3,2)"
sanitize_sql_for_order("id ASC")
# => "id ASC"
只是为了更新 Rails 5+,在撰写本文时,将数组传递给order
will(尝试)清理右侧输入:
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 会报错。
我使用如下内容:
@scoped = @scoped.order Entity.send(:sanitize_sql, "#{@c} #{@d}")
其中 Entity 是模型类。
ActiveRecord::Relation
用扩展sanitized_order
。在Dylan 的带领下,我决定扩展以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
它主要做两件事:
它确保column
参数klass
是ActiveRecord::Relation
.
在我们上面的示例中,它将确保params[:order_by]
是Item
' 列之一。
它确保方向值是“ASC”或“DESC”。
它可能会更进一步,但我发现在接受用户的排序参数时,易用性和 DRYness 在实践中非常有用。