将授权逻辑委托给业务逻辑层
授权是一种业务逻辑,它描述了给定的用户/会话/上下文是否具有执行操作或查看数据片段的权限。例如
“只有作者才能看到他们的草稿”
在 业务逻辑层 中应该执行这种行为。将授权逻辑放在 GraphQL 层中很诱人,如下所示
var postType = new GraphQLObjectType({ name: ‘Post’, fields: { body: { type: GraphQLString, resolve: (post, args, context, { rootValue }) => { // return the post body only if the user is the post's author if (context.user && (context.user.id === post.authorId)) { return post.body; } return null; } } }});
请注意,我们通过检查帖子的 authorId
字段是否等于当前用户的 id
来定义“作者拥有帖子”。你能发现问题吗?我们需要为每个进入服务的入口点复制此代码。然后,如果授权逻辑没有完全同步,用户可能会根据他们使用的 API 看到不同的数据。哎呀!我们可以通过为授权拥有 单一事实来源 来避免这种情况。
在学习 GraphQL 或原型设计时,在解析器中定义授权逻辑是可以的。但是,对于生产代码库,请将授权逻辑委托给业务逻辑层。以下是一个示例
//Authorization logic lives inside postRepositoryvar postRepository = require('postRepository');
var postType = new GraphQLObjectType({ name: ‘Post’, fields: { body: { type: GraphQLString, resolve: (post, args, context, { rootValue }) => { return postRepository.getBody(context.user, post); } } }});
在上面的示例中,我们看到业务逻辑层要求调用者提供一个用户对象。如果您使用的是 GraphQL.js,则 User 对象应该在解析器的第四个参数中的 context
参数或 rootValue
上填充。
我们建议将完全水化的 User 对象而不是不透明的令牌或 API 密钥传递给您的业务逻辑层。这样,我们可以在请求处理管道的不同阶段处理 身份验证 和授权的不同问题。