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

查看:17
本文介绍了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
}

不包括私有字段,但是这不会让人觉得枯燥,因为您将创建许多结构形式彼此 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天全站免登陆