假设我的应用程序是电子商务。有Users
、Orders
和Products
。
您需要进行身份验证(使用 JWT 令牌(才能访问您的user
数据和orders
。此检查在解析器中完成。
但是,Products
是公开的。您无需登录即可查看产品。
当然,User
有Orders
,Order
有Products
如果前端有人正在执行此查询,该怎么办:
query IAmEvil {
products {
orders {
users {
id
name
email
}
}
}
}
这个未经身份验证的家伙将有权访问users
数据。我怎样才能防止这种情况发生?
我是否必须在所有解析器中为所有嵌套查询添加规则?
相关文档:
https://www.apollographql.com/docs/guides/security.html https://www.howtographql.com/advanced/4-security/https://blog.apollographql.com/securing-your-graphql-api-from-malicious-queries-16130a324a6b https://www.prisma.io/forum/t/graphql-security-protect-nested-data/4519
一个可以说更优雅的解决方案是利用行级别安全性 (RLS( 来控制任何特定用户有权访问的数据。虽然这种方法增加了一些复杂性,但如果具有不同访问级别的不同角色的用户访问您的 API,则此方法特别有吸引力。这实际上是后石墨处理身份验证的方式。
您还可以潜在地使用架构指令来保持干燥,并将一些常规访问逻辑应用于一组单独的字段。阿波罗的文档实际上有一个这样做的例子。
除此之外,是的,您的解析器需要具有上下文感知能力,并包含逻辑来限制您公开的数据。
重要的是要指出,这些担忧首先也可以追溯到良好的模式设计。例如,仅仅因为存在关系并不意味着它需要(或应该(向客户公开。订单可能包含一个或多个产品,如果客户端需要显示订单历史记录,则在Order
类型上公开products
字段是有意义的。另一方面,客户是否真的需要知道给定产品的所有订单?
同样,如果我们有一个Order
上的users
字段,在任何特定于用户的上下文之外,这样的字段自然只会反映与订单关联的用户(很可能只是一个用户(。将所有用户作为单个订单上的字段返回是没有意义的。由于 GraphQL 自上而下的性质,一个字段通常只限于其父级的上下文。因此,可能只需要担心根级别的用户上下文。
一个不同的任意示例:
query MyOrders {
orders { # check context for user and limit results to just the logged in user
user { # user will be based on parent (the order), no need to check context
orders { # orders will be based on parent (the user), no need to check context
}
}
}
}
通过合理的架构设计,其他类型的字段的解析器不一定需要执行任何其他上下文检查。
简短的回答是肯定的,但不是在每个级别的嵌套。
对于任何请求,您都有用户(或缺少用户(和图形的路径。 对于必须授权请求的 restful 类型请求,这是完全相同的。 虽然b/c,但解析器可以在任何地方添加,但难度更大。
关于Facebook如何处理这个问题的最好讨论可能在这里 https://blog.apollographql.com/graphql-at-facebook-by-dan-schafer-38d65ef075af
要点是它们有一个函数,负责获取和授权解析器使用。