spring GraphQL字段级授权和空性

nbnkbykc  于 2023-08-02  发布在  Spring
关注(0)|答案(2)|浏览(97)

我们已经在服务器的类型解析器中实现了字段级别的授权,其中只有当用户有权访问该字段时,字段才会返回一个值,否则返回“null”(在扩展中包含信息)。我们不只是返回一个错误(带有空数据响应)的原因是,我们的Web应用程序被具有不同访问级别的各种用户使用,我们不希望(在某些情况下也不能)编写适合每种访问模式的查询。我们的客户端有单独的逻辑来处理授权,这样丢失的信息就可以正确处理。
现在,我们还想在GraphQL模式中添加空性信息,但这在上面处理丢失访问的方法中很困难。如果从技术上讲,一个字段从未从我们的数据返回null,我们希望在模式中也将其标记为不可空。但是,由于缺少授权会在解析GraphQL时使字段为空,所以它并不是在所有情况下都能很好地工作。
我想我唯一的选择是:

  • 从架构中可能受授权检查影响的部分中移除不可空的信息
  • 在客户机上为不同的访问类型构建自定义查询(这至少允许我们返回一个错误,而不是将字段设为“null”,但这意味着要覆盖所有可能的访问规则需要做很多工作)
  • 在GQL验证响应之前,以某种方式将整个字段从响应中删除,但这听起来非常肮脏,而且可能破坏了服务器和客户机之间的GQL“契约”。

有没有其他人处理过GQL中的字段级授权、常见查询和空性,并对如何处理这些问题有其他建议?

luaexgnf

luaexgnf1#

以下是一些想法,希望对您有所帮助。

可空性

在很多情况下,output 类型上的空性 * 通常 * 被认为不是最好的主意。我将在这里引用Production Ready GraphQL(对于任何设计GraphQL模式的人来说,这本书都是值得的,无论如何推荐都不为过):
因此,在设计模式时,我使用以下几条指导原则来确定是否为空:

  • 对于参数,非空值几乎总是更好的,以允许更可预测和更容易理解的API。(如果要添加参数,则可空是避免破坏现有客户端的最佳选择)
  • 返回由数据库关联、网络调用或任何可能在某一天失败的对象类型的字段几乎总是可空的。
  • 如果您知道在执行时已在父对象上加载了对象上的简单标量,则通常可以安全地将其设置为非空。

输出上的空性是危险的一个原因是,如果非空字段最终为空,则整个父对象也将为空。如果父项也是非空的...那么,您很容易无缘无故地破坏整个对象图。This article也有一个体面的总结的情况和最佳做法。

图形ql字段可见性

  • 一种非常简洁的方式来处理每个字段的授权(如果可能),而是为每个用户(而不是租户)提供一个自定义的GraphqlFieldVisibility。这样,您就不会对可空字段产生任何问题,因为用户甚至已经无法查看(或请求)他们无权查看的字段。执行其请求所针对的有效架构已被筛选为仅包括允许的字段。这种方法不适用于需要在决定字段是否可访问之前检查输入或输出的运行时值的字段,但在其他任何地方(例如,用于基于角色或基于访问列表的授权)。

下面是它的伪代码:

//Do this on each request*
GraphQLCodeRegistry codeRegistry = schema.getCodeRegistry().transform(c -> c.fieldVisibility(new AuthVisibility(currentUser)));
GraphQL runtime = GraphQL.newGraphQL(schema.transform(s -> s.codeRegistry(codeRegistry)));

字符串
然后使用当前用户(或任何其他适用的用户)实现AuthVisibility,以确定字段对该用户是否可见。例如,我使用了Spring Security来实现这一点,并调用了它通常调用的相同逻辑来决定当前用户是否可以调用底层的解析器方法。如果你需要的话,我可能可以找出一些代码。

  • 您还可以通过某种方式缓存每个用户会话生成的GraphQL对象,但可能不需要这样做,因为所涉及的转换很简单。
roejwanj

roejwanj2#

将此添加为将来的答案。GraphQL Spec工作组中似乎有一个进步的建议,它将通过允许客户端控制的空性(基本上是更改请求中字段的空性)来解决这个问题:
https://github.com/graphql/graphql-wg/blob/main/rfcs/ClientControlledNullability.md
以下是该提案的摘录:
每个客户端控制的为空性指示符在操作期间覆盖它所附加到的字段的架构定义的为空性。

建议的客户端控制的必需指示符将具有与当前架构定义的Non-Null相似但不完全相同的语义。特别是,如果必填字段解析为null,则null传播将扩展到最近的可选父代,而不是最近的可为null的父代。如果不存在可选的父项,则响应的数据字段将为空。

建议的客户端控制的可选指示符将具有与当前架构定义的默认行为相同的语义。解析为null的字段会针对该字段传回null。此外,标有?的字段充当由必需字段引起空传播的停止点。

相关问题