1

你如何防止人们查询他们不应该在 graphql 中看到的对象的关系?

例如,假设我们有以下数据模型。

type Board {
    id: ID! @unique
    name: String!
    boardUserRoles: [BoardUserRole!]!
}

type BoardUserRole {
    id: ID! @unique
    board: Board!
    user: User!
    role: BoardRole!
}

type User {
    id: ID! @unique
    tasks: [Task!]!
    userName: String! @unique
    boardUserRoles: [BoardUserRole!]!
}

这是一种设置,其中有可以访问某些板的用户。并BoardUserRole确定用户对特定表的角色。

现在,我过来询问我有权使用的董事会并查看其名称。

query {
    board(where: {id: "3"}) {
        id
        name
    }
}

那很好。但是,如果我更改查询,我可以联系系统的其他用户并查看他们的任务。我基本上可以看到与该用户相关的任何内容。

query {
    board(where: {id: "3"}) {
        id
        name
        boardUserRoles {
            user {
                tasks
            }
        }
    }
}

你如何防止这种类型的查询?

4

2 回答 2

1

在@xadm 的帮助下。我能够组合出一个非常适合我的解决方案。

在阅读了这篇关于查询执行如何工作的文章之后。我想出了如何编写字段解析器。字段解析器允许我确定特定字段的解析方式。我为Board: boardUserRoles.

这是我的字段解析器。

Board: {
    boardUserRoles: async (parent: Board, args, ctx, info) => {
        // getting user id from header.
        const userId: string = VerificationHelper.getUserId(ctx);

        // Verifying role of user.
        return VerificationHelper.verifyRole(userId, ["ADMIN"], ctx).pipe(
            map(
                (result: boolean) => {
                    // If the user has an admin role, show the roles
                    if (result) {
                        return parent.boardUserRoles;
                    // If not, map the results to undefined
                    } else {
                        return undefined;
                    }
                }
            )
        ).toPromise();
    }
}

然后,我将该解析器添加到我在 graphql 创建中的解析器列表中。

const server: GraphQLServer = new GraphQLServer({
    typeDefs: "src/schema.graphql",
    resolvers: {
        Query: QueryResolvers,
        Mutation: MutationResolvers,
        Subscription: SubscriptionResolvers,
        ...FieldResolvers, // A file that contains all my field resolvers.
        AuthPayload
    },
    context: (req: any) => ({
        ...req,
        prisma: new Prisma({
            typeDefs: "src/generated/prisma.graphql",
            endpoint: endpoint()
        })
    })
});

这是一个非常基本的字段解析器。它检查用户角色并确定是否应该隐藏数据或显示数据。我浏览了整个架构并发现了其他数据漏洞。我纠正了我用字段解析器找到的那些,现在一切都很好。

感谢@xadm 的帮助,您的参考资料为我指明了正确的方向。

于 2018-08-14T13:45:54.603 回答
0

使用 Prisma 时,您可以通过重新定义应用程序模式中的类型来修改向客户端应用程序公开的数据结构。

您在问题中显示的 SDL 定义对我来说就像Prisma 数据模型。我假设您还有一个 API 服务器(可能使用graphl-yogaor实现apollo-server),它公开将由您的客户端应用程序使用的 GraphQL API。让我们将定义此 API 的 GraphQL 模式称为应用程序模式。在应用程序模式中,您可以按照您希望将类型公开给客户的方式重新定义数据模型中的类型。

这是一个简单的例子:

User假设您的 Prisma 数据模型中有以下类型:

type User {
  id: ID! @unique
  email: String! @unique
  password: String!
  name: String!
  posts: [Post!]!
}

现在,您不想将其暴露password给您的客户。因此,您可以做的是以User您的客户应该能够访问它的方式重新定义类型。以下是如何在应用程序模式(通常称为schema.graphql)中定义它:

type User {
  id: ID!
  email: String!
  name: String!
  posts: [Post!]!
}

您可以在此处找到此示例的运行版本。此外,如果您对应用程序模式和数据模型的术语感到困惑,我建议您阅读Prisma 文档的这一部分。

于 2018-08-14T07:47:40.210 回答