GraphQL 中的权限管理:最佳实践

阅读时长 6 分钟读完

GraphQL 是近年来广受欢迎的一种 API 设计语言,它让前端开发者能够根据自身需求自由地获取远程数据。但是,不同于传统的 RESTful API,在 GraphQL 中没有明确的 URL 和动词来限制和描述数据操作。这使得前端和后端之间的数据交互更为复杂,同时也引出了一些安全性和访问权限等方面的问题,因此在实际开发中需要进行有效的权限管理。

本文将介绍 GraphQL 中的一些最佳实践,以及如何通过这些实践来加强对远程数据的访问权限管理。

GraphQL 中的权限问题

在 GraphQL 中,所有数据操作都应该通过一个单一的入口(通常是 /graphql)来进行。这就意味着,如果未对访问者进行权限控制,所有人都可以通过该入口来访问和修改数据。

而要在 GraphQL 中对某个字段或数据类型进行权限控制,需要在后端结构定义(Schema)中对其进行限制。这里需要注意的是,这些限制必须在运行时才能进行判断,因此需要在服务器端进行代码编写和控制。

最佳实践:控制字段和类型的访问权限

最常见的权限管理需求就是限制某个字段或类型的访问权限。在下面的示例中,我们仅允许拥有特定 token 的用户才能查看 profile 字段:

-- -------------------- ---- -------
----- --------- - -
  ------ -
    ------------ ----- -------- -
      -- ------------------ -----
      -- ------------------ --- --------- -
        ----- --- -----------------
      -

      -- ---------- --------------
      ------ -
        --- --
        ----- -------
        ------ ------------------
      --
    -
  -
--

我们在 profile 字段的 resolver 中,首先检查用户是否携带了特定的 token。如果没有,我们将抛出错误以阻止访问。否则,我们可以安全地返回数据。

类似的,我们也可以限制某个类型的访问权限。在下面的示例中,我们禁止未认证的用户访问系统管理员的记录:

-- -------------------- ---- -------
----- -------- - --- -------------------
  ----- -------
  ------- -
    --- - ----- ---------- --
    ----- - ----- ------------- --
    -------- -
      ----- ---------------
      ------------- ----- -------- -
        -- ---------------- ------- --
        -- ------------------ --- -------- -- -------------- -
          ----- --- -----------------
        -
        ------ -------------
      -
    -
  -
---

这里我们在 isAdmin 字段的 resolver 中判断了用户是否为系统管理员,如果不是则抛出错误。

最佳实践:控制查询和变更权限

除了限制某个字段或类型的访问权限,我们还可以在 GraphQL 中限制整个查询或变更操作的访问权限。

我们可以通过定义 middleware 函数来控制所有传入的查询或变更操作。这里有一个例子,当用户未登录时,我们将拒绝所有的查询和变更操作:

-- -------------------- ---- -------
-- ----- ----------
-------- ----------------------- ---- ----- -
  -- ----------- -
    ------ -----------------------------
  -
  -------
-

-- - ---------- ----- ------- ---
----- --- - ----------
------------------- ------------------- -------------
  ------- --------
----

这里,我们定义了 isAuthedMiddleware 来判断用户是否已登录。如果未登录,则返回 401 状态码。

之后,我们将 isAuthedMiddleware 作为 middleware 函数,通过 app.use() 注入到 GraphQL 服务中。这样,所有经过 /graphql 接口的请求都必须先经过这个 middleware,如果未通过则直接拒绝。

最佳实践:控制查询结果细节

在 GraphQL 中,前端可以精确地控制返回结果的细节。但这也可能引入一些安全性问题,比如:某个查询应该返回什么级别的数据、是否显示敏感数据等。在这些情况下,我们可以通过 HOC(高阶组件)来控制返回值的细节:

-- -------------------- ---- -------
-- -- --- --------
-------- ------------------------------ -
  ----- ---------- - ------- -- -
    ----- - ----------- - - ------
    ----- -------- - - --------- ------ - ------- -------------- - --
    ------ ------------------
  --
  ------ -----------
-

-- -- --- ------- --------
----- --------- - -
  ------ -
    -------- --------------------------- ----- -------- -- -
      ------ ----------------------------
    ---
    -- --------
  --
  --------- -
    ----------- --------------------------- ----- -------- -- -
      ----- - --- ----- - - -----
      ------ ------------------ -------
    ---
    -- --------
  -
--

这里我们定义了一个 withLimitToOwnRecords 的 HOC,它将包装我们的 resolver 并通过 currentUser 测试数据,把其与指定记录或类型对象并检查是否属于该用户,如果不属于则抛出错误以阻止访问。

结论

在 GraphQL 中,为了加强对远程数据的访问权限管理,需要对字段和类型的访问权限、查询和变更权限以及查询结果细节等方面进行限制。

本文介绍了一些最佳实践,如限制字段和类型的访问权限、控制查询和变更权限以及通过 HOC 动态控制返回值。通过掌握这些最佳实践,前端开发者可以更加安全地访问并使用远程数据。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67166cc1ad1e889fe21c7adc

纠错
反馈