【问题标题】:GraphQL: How to restrict fields server-side across queries?GraphQL:如何限制跨查询的服务器端字段?
【发布时间】:2017-11-22 07:38:48
【问题描述】:

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

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

如果我自己查询,返回所有字段也没关系,因为信息是我的。因此,将creditCardNumber 返回给客户端并不是什么大问题。但是如果我要查询其他人,我应该只能访问返回用户的公共信息。返回creditCardNumber 会很糟糕。即使我没有在客户端上编写查询代码来执行此操作,如何防止恶意用户深入研究代码、更新客户端查询以包含 creditCardNumber 并执行它?

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

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

它不包括私有字段,但是这不会让人感觉 DRY,因为您将创建许多在结构上彼此 90% 相似的类型。

有没有更简洁的方法来实现这一点,不会创建不必要的类型或重复字段?

【问题讨论】:

    标签: graphql


    【解决方案1】:

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

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

    要访问“上下文”数据,例如当前用户,GraphQL 让您在执行 graphql 函数时传递一个对象 context

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

    你会在每个字段resolve函数签名中找到这个对象:

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

    所以你可以做的是在上下文中传递当前登录的用户:

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

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

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

    如果您使用graphql-express,则上下文默认为请求and you can customize it

    【讨论】:

    猜你喜欢
    • 2017-06-24
    • 1970-01-01
    • 2017-05-16
    • 2019-06-30
    • 2021-07-13
    • 2019-01-27
    • 1970-01-01
    • 2017-08-28
    • 2019-01-09
    相关资源
    最近更新 更多