用于身份验证检查的 GraphQL 解析器中间件

GraphQL resolver middleware for auth check

我有一个 GraphQL API 混合 public 和私人查询和变异。我正在寻找一种方法来检查操作是否需要对用户进行身份验证以及权限检查器,以便用户只能修改自己的数据。

我注意到解析器函数有第四个参数,info,其中包括 path.key,其中 returns 操作的名称(已记录 here)。

我的解决方案是在每个解析器中添加一个检查器函数,如下所示:

// modify user details
resolve: async (parent, args, { mongo: { User }, loggedUser }, info) => {
    // auth check
    authChecker(info.path.key, loggedUser, args.id);

  // continue resolving
},

在另一个文件中:

function authChecker(operationName, loggedUser, userId) {
  if (PUBLIC_OPERATIONS.includes(operationName) {
    // public operation
    return true;
  } else {
    // private operation
    if (args.id) {
      // private operation that requires a permission check
      ...
    } else {
      // private operation that only requires user to be logged in
      ...
    }
  }
}

如果条件不满足,函数 returns 为真或抛出错误。

我想知道这是否是一个好的解决方案,或者是否有一种方法可以通过中间件以某种方式完成,这样我就不必在每个解析器中重复代码。问题是如果我使用中间件,我将无法访问操作名称。有什么建议吗?

使用中间件应该是可行的,但会很痛苦,因为您必须自己解析查询。我认为最干净的方法是使用模式级解析器,它可用于 graphql-tools.

const {makeExecutableSchema, addSchemaLevelResolveFunction} = require('graphql-tools')

const schema = makeExecutableSchema({typeDefs, resolvers})
addSchemaLevelResolveFunction(schema, (root, args, context, info) => {
  // check info to see if query is private and throw if user isn't authenticated
})
// use the schema like normal
app.use('/graphql', graphqlHTTP({schema}))

解析器不需要return任何东西;它只需要在身份验证失败时抛出或 return 一个被拒绝的 Promise。有关使用 graphql-tools 生成模式的更多信息,请查看文档 here.