按广度限制 GraphQL 查询

Limit GraphQL Queries by Breadth

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

但是,我还没有找到任何东西可以保护 GraphQL 服务器免受 "wide" 查询的影响,该查询只是在同一请求中提取了太多字段实例,即:

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 个这样昂贵的对象。

有没有人知道这样的模块等等?或者是否有不同的方法来实现这种类型的限制?

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

尽管我认为这应该是 GraphQL 的核心功能,但似乎不存在这样的 module/implementation,特别是因为这可能是一个大型 DoS 漏洞,并且如前所述,cost/complexity 分析在某些情况下可能会矫枉过正(如在我们的特定情况下)。

我最终编写了一个简单的 @resourceLimit 指令来限制使用别名多次请求单个字段。这仍然为我们提供了在我们认为可能有必要时添加 cost/complexity 分析的选项,但就目前而言,它满足了我们有限的要求。