ApolloServer 2.0上下文和GraphQL API的公共/私有部分

时间:2018-08-23 08:31:40

标签: javascript express graphql apollo-server

无论如何我都不是专业人士,但我已经开始使用ApolloServer / Express后端托管一个站点,在那里我将为会员提供公共部分和私有部分。我在登录突变中生成JWT令牌,并将其传递给客户端。

对于上下文,我想检查是否设置了令牌,并基于此句柄允许使用什么GraphQL查询。我的Express / Apollo服务器目前看起来像这样。

const server = new ApolloServer({
  typeDefs,
  resolvers,
  context: async ({ req }) => {
    // get the user token from the headers
    const token = (await req.headers.authorization) || '';

    if (token) {
      member = await getMember(token);
    }
  }
});

问题在于,这会从任何查询中锁定GraphQL API,例如,我希望/需要达到注册/登录突变。

任何人都可以对此发表一些看法,以帮助我了解如何使它起作用。

1 个答案:

答案 0 :(得分:0)

我这样做的方式是,即使在graphql服务器之前,我也将构造auth中间件,因为有时需要在GraphQL模式中的其他中间件中也包含有关经过身份验证的用户的信息。将添加一些代码,您需要完成该代码

const auth = (req, res, next) => {
  if (typeof req.headers.authorization !== 'string') {
    return next();
  }

  const header = req.headers.authorization;
  const token = header.replace('Bearer ', '');
  try {
    const jwtData = jwt.verify(token, JWT_SECRET);
    if (jwtData && jwtData.user) {
      req.user = jwtData.user;
    } else {
      console.log('Token was not authorized');
    }
  } catch (err) {
    console.log('Invalid token');
  }
  return next();
};

这样,如果设置了正确的令牌,我会将用户注入每个请求中。然后,在apollo服务器2中,您可以执行以下操作。

const initGraphQLserver = () => {
  const graphQLConfig = {
    context: ({ req, res }) => ({
      user: req.user,
    }),
    rootValue: {},
    schema,
  };

  const apolloServer = new ApolloServer(graphQLConfig);
  return apolloServer;
};

此功能将启动ApolloServer,您将在适当的位置应用此中间件。在套用阿波罗伺服器2之前,我们需要拥有auth中间件

app.use(auth);

initGraphQLserver().applyMiddleware({ app });

假设应用为

const app = express();

现在,您将把jwtData用户中的用户作为“用户”注入到每个解析程序的上下文中,或者在其他中间件中的req.user中注入,您可以像这样使用它。这是我的询问,用于说明哪个用户已通过身份验证

  me: {
    type: User,
    resolve: async (source, args, ctx) => {
      const id = get(ctx, 'user.id');

      if (!id) return null;

      const oneUser = await getOneUser({}, { id, isActive: true });
      return oneUser;
    },
  },

我希望即使使用分段代码,一切都有意义。随时问其他问题。肯定有更复杂的auth,但是对于一个简单的应用程序来说,这个基本示例通常就足够了。

最佳大卫