假设我在https://api.service.com/graphql
处有一个graphql端点,该端点用于在https://www.service.com
+一个iOS应用程序+一个Android应用程序上构建公司的官方UI。我想向公众公开此API,以便第三方应用程序可以通过查询数据在此API之上构建,但是我不希望它们能够抓取我的整个数据库。
假设我们有一个类型:
type Thing {
# public fields
field1: String
field2: String
# fields only available in the official UI
field3: String
field4: String
}
和查询:
{
things(limit: Int!, offset: Int): [Thing]
}
仅允许公司的官方UI查询所有Thing
字段并遍历所有内容的最佳方法是什么?第三方开发人员仅应针对每件事情查询field1
和field2
,并对他们可以访问多少东西有一些限制。
我考虑过要求每个客户端在每个查询请求中都包含一个令牌,以便可以检测到官方网站,iOS应用程序和Android应用程序并将其“列入白名单”。但是,如果阻止令牌存储在客户端,是什么会阻止某人深入研究您的javascript / app捆绑并找到该令牌?
我考虑过发布具有两个不同模式/一组限制的两个不同API端点,例如:
https://api.service.com/graphql
-公开记录并使用有限的架构。
https://api.service.com/graphql-anon
-官方UI私下使用,并包含功能齐全/不受限制的架构。
但是,又一次阻止用户询问应用程序包并发现https://api.service.com/graphql-anon
端点存在并使用它的原因呢?
答案 0 :(得分:2)
首先,顺便说一句:出于多种原因,我通常会建议为您的公共API使用单独的架构和终结点:
那就是说,显然,维护两个单独的API会产生一定的成本,因此这并不是在所有情况下都合适的解决方案。
回到当前的问题...不管上面的考虑如何,通常,您将使用基于令牌的身份验证来限制对全部或部分API的访问,但是您不会将此令牌存储为应用程序的一部分。典型的基本流程如下:
服务器使用令牌建立用户身份,然后可以通过请求的上下文将其提供给每个GraphQL解析器功能。这使您可以仅在用户通过身份验证(或者她的角色允许访问该字段)时才有效地仅返回特定字段的数据。如果用户无法访问该字段,则根据类型,它只能返回null或空数组。
当然,您还可以为未认证的用户提供一些小的查询。这种方法使您可以根据角色而具有不同的访问级别(因此,“管理员”用户可能比“标准”用户具有更多的查询或字段,“标准”用户比未经身份验证的用户具有更多的访问权限)。
对于公共API,您可以通过类似的方式使用客户端令牌的某种组合来识别第三方客户端(也许它们不必登录,但可以使用令牌的哈希值和您所使用的秘密例如分配给他们)。如果您拥有共享模式,则可以同时支持两种身份验证机制。这样,“第三方客户端”就可以成为另一个具有某些字段子集访问权限的角色。