GraphQL 是一种用于构建 API 的查询语言。它被广泛应用于前端开发中,因为它允许客户端指定需要哪些数据。但是,GraphQL API 对于攻击者来说也是一个很大的诱惑,可能被用于 DOS(拒绝服务攻击)。在这篇文章中,我们将讨论 GraphQL API 的安全性问题,并介绍一些防止 DOS 攻击的最佳实践。
GraphQL 的 DOS 攻击
DOS 攻击是指故意通过向一个或多个服务器发送大量的请求来使该服务器停止响应其他合法请求的攻击。在 GraphQL 中,攻击者可以使用查询的复杂性来触发 DOS 攻击。在一个复杂的查询中,可能包含多个嵌套的字段、操作、变量和分页操作。攻击者可以通过这些查询中的超时和过多资源使用来使服务器不可用。
例如,一个攻击者可能会使用以下查询:
-- -------------------- ---- ------- ----- - ----- - -- ---- ----- - -- ----- -------- - -- ------- ------- - -- ------- - - - - -
这个查询将返回所有用户的 id、姓名、所有帖子的 id 和标题、帖子下所有评论的 id 和内容,以及所有回复的 id 和内容。攻击者可以使用此查询来产生大量资源的使用量,使 GraphQL 服务器难以应对。
防止 GraphQL 的 DOS 攻击
以下是防止 GraphQL DOS 攻击的最佳实践:
1. 限制查询的复杂度
一旦请求的查询变得太复杂,服务器就会超时或过度使用资源。因此,您需要限制查询的复杂度。可以使用 Apollo Server 中的 graphql-depth-limit 中间件来限制查询的深度。也可以使用 graphql-query-complexity 中间件,它将查询复杂度基于字段、参数等计算。
下面是一个使用 graphql-depth-limit
中间件的示例:
const depthLimit = require("graphql-depth-limit"); const server = new ApolloServer({ schema, validationRules: [depthLimit(5)], });
以上代码中,我们将查询深度限制为 5。
2. 使用延迟加载
如果您的 GraphQL 查询存在嵌套查询,则可以考虑使用延迟加载(defer)和批量加载(batch)来优化性能。使用 @defer
和 @stream
指令可以将查询中的字段分批发送,并且只在需要时才返回。这将减少服务器的负载。
-- -------------------- ---- ------- ----- - ----- - -- ---- ----- ------ - -- ----- -------- - -- ------- ------- ------ - -- ------- - - - - -
在上面的示例中,我们使用 @defer
取消立即返回 posts
字段的响应。GraphQL 服务器将等待现有查询完成,然后再返回查询结果。
3. 限制并发请求数量
限制并发请求数量可以防止攻击者发送大量请求,消耗服务器的资源。可以使用 graphql-rate-limit
中间件来实现并发限制。
const rateLimit = require("graphql-rate-limit"); const server = new ApolloServer({ schema, validationRules: [rateLimit({ max: 50, window: "1m" })], });
在上面的示例中,我们将限制每分钟最多 50 个请求。如果超过限制,服务器将返回一个错误。
4. 限制查询的大小
限制查询的大小将防止客户端发送非常大的查询。可以使用 graphql-validation-complexity
中间件来限制查询的大小。
const { createComplexityLimitRule } = require("graphql-validation-complexity"); const server = new ApolloServer({ schema, validationRules: [createComplexityLimitRule(1000)], });
在上面的示例中,我们将限制查询大小为 1000。
结论
在开发 GraphQL API 时,安全性问题必须得到重视。防止 DOS 攻击是其中之一。通过限制查询的复杂性、使用延迟加载、限制并发请求数量和限制查询的大小等方法可以有效地防止 GraphQL 的 DOS 攻击。在实际开发中,您应该根据不同情况来选择最适合您的方法,确保您的 GraphQL API 在面对攻击者时仍然能够稳定运行。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67496ba4a1ce0063545dc5d3