代码之家  ›  专栏  ›  技术社区  ›  prolink007

用graphql防止关系数据泄漏攻击

  •  1
  • prolink007  · 技术社区  · 6 年前

    如何防止人们查询在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
                }
            }
        }
    }
    

    如何防止此类查询?

    2 回复  |  直到 6 年前
        1
  •  1
  •   prolink007    6 年前

    在@xadm的帮助下。我能想出一个对我非常有效的解决方案。

    在阅读了这篇关于如何 query execution works 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();
        }
    }
    

    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的帮助,你的推荐人给了我正确的方向。

        2
  •  0
  •   nburk    6 年前

    使用Prisma时,可以通过在 应用程序架构

    您在问题中显示的SDL定义看起来像 Prisma数据模型 对我来说。我假设您也有一个API服务器(可能用 graphl-yoga apollo-server )它公开了客户机应用程序将要使用的GraphQL API。我们将定义这个API的GraphQL模式称为 应用程序架构 . 在应用程序架构中,您可以 数据模型中的类型以您希望将它们公开给客户机的方式。

    下面是一个简单的例子:

    假设你有 User

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

    现在,你不想暴露 password 用户 schema.graphql ):

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

    你可以找到这个例子的运行版本 here . 另外,如果您对应用程序模式和数据模型的术语感到困惑,我建议您阅读 this

    推荐文章