NodeJS 使用中间件保护GraphQl查询和突变

nbewdwxp  于 2023-10-17  发布在  Node.js
关注(0)|答案(2)|浏览(128)

我正在开发一个express应用程序,并尝试使用graphql。我已经开始不使用以前创建的旧端点。问题是我的一些旧端点受到中间件的保护,比如:

router.get(
  "/",
  [auth.verifyToken, auth.checkRole(["role1", "role2"])],
  someController.getAllThings
);

所以我的问题是如何保护查询和突变与中间件?

fjaof16o

fjaof16o1#

在graphql中,你通常有一个端点,你的graphql服务器在那里运行,你为你的服务器提供一个上下文函数,每个传入的请求都会被调用。这是您可以执行身份验证/授权的地方。context函数被传递了一个request对象,您可以使用它来验证token并检查用户角色。这个上下文函数的结果可供所有解析器使用,因此您可以决定需要保护哪些查询或变化。

dgsult0t

dgsult0t2#

在GraphQL世界中,中间件的角色在某种程度上被指令所取代。因此,如果我们将一个变化或查询看作是express服务器中的一个端点,如果我们想添加一个函数来检查用户是否经过身份验证,那么我们将生成一个isAuthdirective
在GraphQL中,我们使用特殊的@字符作为指令。
假设我们有一个返回经过身份验证的用户数据的查询。

const typeDefs = `#graphql

  type Query {
    me: User @isAuth
  }

  type User {
    id: Int
    username: String
  }
`;

const resolvers = {
  Query: {
    me() {
      return {
        id: 1,
        username: "exampleUser"
      };
    },
  },
};

正如你所看到的,我们直接将指令应用于查询field definition
现在让我们以@isAuth指令为例。首先,我们将该指令添加到模式中。

const typeDefs = `#graphql

  directive @isAuth on FIELD_DEFINITION
  
  type Query {
    me: User @isAuth
  }

  type User {
    id: Int
    username: String
  }
`;

这让GraphQL知道isAuth指令存在。
接下来是Transformer函数,它保存身份验证逻辑。

function authenticatedDirectiveTransformer(schema, directiveName) {
  return mapSchema(schema, {
    // Executes once for each object field in the schema
    [MapperKind.OBJECT_FIELD]: (fieldConfig) => {
      // Check whether this field has the specified directive
      const authorizationDirective = getDirective(schema, fieldConfig, directiveName)?.[0];

      if (authorizationDirective) {
        // Get this field's original resolver
        const { resolve = defaultFieldResolver } = fieldConfig;

        // Replace the original resolver with a function that *first* calls
        // the original resolver, then runs your auth logic
        fieldConfig.resolve = async function (source, args, context, info) {
          // Your authentication logic...
          return resolve(source, args, context, info);
        };
        return fieldConfig;
      }
    },
  });
}

上面的Transformer函数基本上是在每个GraphQL操作中查找对象字段(Query对象,Mutation对象,.)上的isAuth指令,如果找到它,它将运行resolve函数,其中包含您的逻辑。
我们需要做的最后一件事是将Transformer函数应用于GraphQL模式。

let schema = makeExecutableSchema({
  typeDefs,
  resolvers,
});

// Transform the schema by applying directive logic
schema = authenticatedDirectiveTransformer(schema, 'isAuth');

相关问题