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

Posted

技术标签:

【中文标题】ApolloServer 2.0 上下文和 GraphQL API 的公共/私有部分【英文标题】:ApolloServer 2.0 context and public/private parts of the GraphQL API 【发布时间】:2019-01-29 13:46:54 【问题描述】:

我不是专业人士,但我已经开始使用 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】:

我这样做的方式是,我什至会在 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 server 2 中,您可以按如下方式进行操作。

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

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

此函数将启动 ApolloServer,您将在正确的位置应用此中间件。申请 apollo server 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;
    ,
  ,

我希望即使使用分段代码,一切都有意义。随时问任何问题。肯定有更复杂的身份验证,但这个基本示例通常对于简单的应用程序来说已经足够了。

最好的大卫

【讨论】:

感谢您抽出宝贵时间。我现在只是盯着代码看,因为我现在正在工作,但今晚会坐下来试试看:)我想我理解了大部分内容:)会得到结果。 我试了一下,但是在我不需要的 ApolloServer 的上下文中它是不是很多东西?不确定上下文的每个参数来自哪里。我确实了解 express 的 auth 中间件,并且它需要在应用中间件之前执行。 嗨伙计,很抱歉造成混乱,我是从我的项目中复制的,因此还有很多额外的东西。我已经删除了它,所以希望现在更清楚了。请注意,在我的项目中,我使用了基于类的方法定义的模式,来自 graphql-js 库而不是 graphql-tools,因此你有 typeDefs、解析器等,而不是 apollo 服务器构造函数中的模式。 感谢您的信息。我想我现在明白了:)

以上是关于ApolloServer 2.0 上下文和 GraphQL API 的公共/私有部分的主要内容,如果未能解决你的问题,请参考以下文章

如何在 ApolloServer 中获取 req.user

如何在 Apollo Server 中正确键入上下文对象?

Apollo Server:如何从 REST API 数据源访问 Dataloader 中解析器之外的“上下文”

阿波罗服务器 2.0。在文档中找不到类型“上传”

使用 ExpressJS 访问 Apollo Server 中的 Request 对象

Apollo 服务器 2.0 不能与 join-monster-graphql-tools-adapter 和 oracle 一起使用