按宽度限制 GraphQL 查询

Posted

技术标签:

【中文标题】按宽度限制 GraphQL 查询【英文标题】:Limit GraphQL Queries by Breadth 【发布时间】:2020-03-31 20:14:18 【问题描述】:

有许多文章、教程甚至模块可以通过检查查询深度、成本或限制 GraphQL 服务器的高连续请求率(DoS 攻击)来限制恶意递归查询。

但是,我无法找到任何可以保护 GraphQL 服务器免受“宽”查询影响的方法,该查询只是在同一请求中提取了太多字段实例,即:

query MaliciousQuery 
  alias1: fieldName  subfileld1 subfiled2 ...
  alias2: fieldName  subfileld1 subfiled2 ...
  ...
  alias10: fieldName  subfileld1 subfiled2 ...
  ...
  alias100: fieldName  subfileld1 subfiled2 ...
  ...
  alias1000: fieldName  subfileld1 subfiled2 ...
  ...

是的,GraphQL 允许客户询问他们需要什么,但在某些情况下,我们可能希望限制特定类型的对象的数量,尤其是在获取此类对象的成本很高的情况下。我应该提到分页在我的用例中是不可取的。

当然,一种方法是限制查询字符串的总长度,但这是实现此目的的一种粗略方法,并且对于甚至不引用实际昂贵对象的复杂查询请求会产生意想不到的副作用。也可以使用成本分析,但对于这么简单的事情来说似乎有点过头了,而且还会引入其他复杂性。

如果我们可以在模式上设置一个限制指令,我们可以指定类似的东西,那就太好了

@perRequestLimit(count: 5)

因此客户端在单个查询中不能请求超过 5 个这些昂贵的对象。

有人知道这样的模块吗?或者有没有其他方法可以实现这种类型的限制?

【问题讨论】:

【参考方案1】:

更好的方法是简单地使用查询成本或查询复杂性分析。有existing libraries 可以解析请求的查询,确定成本并在成本超过设置的允许值时拒绝请求。这使您可以轻松控制查询的深度和广度,而不必将单个查询“列入白名单”,这将是不可扩展的。

【讨论】:

【参考方案2】:

尽管我认为这应该是 GraphQL 的核心功能,但似乎不存在这样的模块/实现,特别是因为这可能是一个大型 DoS 漏洞,并且如前所述,成本/复杂性分析在某些情况下可能是矫枉过正的(在我们的特定场景中)。

我最终编写了一个简单的@resourceLimit 指令来限制使用别名多次请求单个字段。当我们认为可能有必要时,这仍然使我们可以选择添加成本/复杂性分析,但目前,它满足了我们有限的需求。

【讨论】:

以上是关于按宽度限制 GraphQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

按关系查询 GraphQL?

如何按 Graphql 查询结果分组

按当前时间戳的 GraphQL 查询过滤器

如何按字符串中的数字对graphql查询进行排序?

如何在 graphql 查询中按文件扩展名过滤

在 GraphQL 查询中分组后如何限制和跳过标签列表页面的分页?