GraphQL:如何在查询中限制服务器端的字段? [英] GraphQL: How to restrict fields server-side across queries?

查看:63
本文介绍了GraphQL:如何在查询中限制服务器端的字段?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我的用户类型包含以下字段:

Let's say I have a User type that contains the following fields:

type User {
  name: String
  username: String
  someOtherField1: String
  someOtherField2: String
  someOtherField3: String
  someOtherField4: String
  creditCardNumber: String
}

如果我要查询自己,可以返回所有字段,因为该信息属于我.因此,将 creditCardNumber 返回给客户端并不是什么大问题.但是,如果我要查询其他人,则只能访问返回用户的公共信息.返回 creditCardNumber 会很糟糕.即使我没有在客户端上对查询进行编码,是什么会阻止恶意用户挖掘代码,更新客户端查询以包含 creditCardNumber 并执行它呢?

If I am querying for myself, it's okay to return all fields, because the information is mine. So returning creditCardNumber to the client is no biggie. But if I am querying for someone else, I should only be able to access the public info on the returned user. Returning creditCardNumber would be terrible. And even if I don't code the query on the client to do so, what would prevent a malicious user from digging into the code, updating the client-side query to include creditCardNumber, and executing it?

在GraphQL中跨查询实现这种级别的字段限制的最佳方法是什么?到目前为止,我对此的唯一想法是创建一个单独的 UserSearch 类型,即

What is the best way to achieve this level of field restriction across queries in GraphQL? My only thought on this so far is to create a separate UserSearch type, i.e.

type UserSearch {
  name: String
  username: String
  someOtherField1: String
  someOtherField2: String
  someOtherField3: String
  someOtherField4: String
}

不包含私有字段,但是这不会让人感到DRY,因为您将创建许多彼此之间结构相似度达90%的类型.

which excludes the private fields, however this does not feel DRY as you'd be creating many types that are 90% similar in structure form each other.

是否有一种更清洁的方法来实现此目的,而不会创建不必要的类型或重复的字段?

Is there a cleaner way to implement this, that doesn't create unnecessary types or duplicate fields?

推荐答案

默认情况下,GraphQL类型可能是类型,这意味着您可以向任何字段返回null.

By default, GraphQL types are maybe types, which means you can return null to any field.

这意味着,在 creditCardNumber 字段的 resolve 函数内部,您可以检查当前用户是否是正在获取的用户,如果是,则返回该数字.否则,您将返回null.

Which means, inside the resolve function of your creditCardNumber field, you could check if the current user is the user being fetched, and if so, you return the number. Otherwise, you return null.

要访问上下文"数据(例如当前用户),GraphQL允许您在执行graphql函数时传递对象 context :

To access "contexted" data such as the current user, GraphQL let you pass an object context when executing the graphql function:

graphql(schema, query, rootValue, context) // <-- the last parameter

您将在每个域中找到此对象 resolve 函数签名:

And you will find this object in each field resolve function signature:

...
resolve: (object, args, context) => {
  // Third argument is your object
},
....

因此,您可以做的是在上下文中传递当前登录的用户:

So what you can do, is pass the current logged user in the context:

graphql(schema, query, rootValue, { user: getCurrentLoggedUser() })

在您的 User 类型中,在 creditCardNumber 字段解析函数内:

And in your User type, inside the creditCardNumber field resolve function:

creditCardNumber: {
  ...
  resolve: (user, args, context) => {
    if (user.id === context.user.id)
      return user.creditCardNumber;

    return null;
  },
  ...
}

如果您使用的是 graphql-express ,默认情况下,上下文是请求,

If you are using graphql-express, the context is by default the request, and you can customize it.

这篇关于GraphQL:如何在查询中限制服务器端的字段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆