【发布时间】:2016-02-06 15:48:27
【问题描述】:
Facebook 的官方说法是 Relay 是“intentionally agnostic about authentication mechanisms”。在 Relay 存储库中的所有示例中,身份验证和访问控制是一个单独的问题。在实践中,我还没有找到一种简单的方法来实现这种分离。
Relay 存储库中提供的示例都具有带有viewer 字段的根模式,假设只有一个用户。该用户可以访问所有内容。
然而,实际上,一个应用程序有很多用户,每个用户对每个节点的访问权限都不同。
假设我在 JavaScript 中有这个架构:
export const Schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: () => ({
node: nodeField,
user: {
type: new GraphQLObjectType({
name: 'User',
args: {
// The `id` of the user being queried for
id: { type: new GraphQLNonNull(GraphQLID) },
// Identity the user who is querying
session: { type: new GraphQLInputObjectType({ ... }) },
},
resolve: (_, { id, session }) => {
// Given `session, get user with `id`
return data.getUser({ id, session });
}
fields: () => ({
name: {
type: GraphQLString,
resolve: user => {
// Does `session` have access to this user's
// name?
user.name
}
}
})
})
}
})
})
});
从查询用户的角度来看,某些用户是完全私密的。其他用户可能只向查询用户公开某些字段。因此,要获取用户,客户端不仅必须提供他们正在查询的用户 ID,而且还必须标识自己,以便进行访问控制。
这似乎很快就变得复杂了,因为控制访问的需求会逐渐渗透到图表中。
此外,我需要控制每个根查询的访问权限,例如 nodeField。我需要确保每个节点都实现了nodeInterface。
所有这些似乎都是重复性的工作。是否有任何已知的模式可以简化这一点?我是不是想错了?
【问题讨论】:
-
我认为如果 Relay 中有一些中间件位于执行引擎之上并根据会话信息重写查询 AST,那将是非常酷的。
-
你有没有得到一个很好的例子/答案?我正在寻找有关使用中继的令牌身份验证(无会话)的信息,但很难找到任何东西
-
@GreenRails 不在这里,但我想出了如何去做。这很不错!基本上,对我来说,关键是弄清楚你可以将东西放入 GraphQL “rootValue”,它在所有分辨率级别都可用。如果您使用的是 express 中间件,可以这样完成:gist.github.com/dminkovsky/…。任何实现都可以这样做。然后,根据下面的答案,您还可以采用“面向查看器”的方法来加载数据以协助 ACL。 github.com/facebook/dataloader 是一个很好的辅助工具。
-
@GreenRails 刚刚添加了答案
标签: javascript graphql relayjs graphql-js