如何在 GraphQL 中实现验证和授权

GraphQL 是一种强大的 API 查询语言,它提供了比传统 RESTful API 更好的数据查询和操作方式。然而,GraphQL 的强大和灵活性也带来了一些安全风险,例如未经身份验证或未经授权的查询和操作。因此,在构建 GraphQL API 时,验证和授权是必不可少的。

本文将介绍如何在 GraphQL 中实现验证和授权,并提供示例代码以帮助您更好地理解和应用这些概念。

验证

验证是确定用户身份的过程。在 GraphQL 中,验证通常涉及使用令牌或其他凭据来标识用户,并确保用户有权访问所请求的数据。

1. 使用 HTTP 头部进行验证

在 GraphQL 中,可以使用 HTTP 头部来传递验证令牌。例如,可以使用 Authorization 头部来传递用户的访问令牌。以下是一个示例查询,它使用 Authorization 头部来传递访问令牌:

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

HTTP 请求头部:

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

在服务器端,可以解析 HTTP 头部来获取访问令牌,并使用该令牌来验证用户身份。以下是一个示例 Node.js 代码片段,用于解析 Authorization 头部并验证访问令牌:

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

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

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

在上面的代码中,我们使用 jsonwebtoken 库来解析和验证访问令牌。如果验证成功,我们将用户信息添加到请求对象中,以便后续的查询和操作可以使用该信息。

2. 使用 GraphQL 变量进行验证

除了使用 HTTP 头部进行验证之外,还可以使用 GraphQL 变量来传递访问令牌。以下是一个示例查询,它使用 GraphQL 变量来传递访问令牌:

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

变量:

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

在服务器端,可以解析 GraphQL 变量来获取访问令牌,并使用该令牌来验证用户身份。以下是一个示例 Node.js 代码片段,用于解析 GraphQL 变量并验证访问令牌:

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

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

在上面的代码中,我们将访问令牌作为查询参数传递给 me 查询,并在解析器中验证该令牌。如果验证成功,我们将返回与用户 ID 相关联的用户信息。

授权

授权是确定用户是否有权访问某个资源的过程。在 GraphQL 中,授权通常涉及使用角色或权限来限制用户对数据的访问。

1. 基于角色的授权

基于角色的授权是一种常见的授权策略,它使用用户角色来确定用户是否有权访问某个资源。在 GraphQL 中,可以使用自定义指令来实现基于角色的授权。

以下是一个示例查询,它使用 @hasRole 指令来限制只有管理员才能访问用户列表:

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

在服务器端,可以编写自定义指令解析器来实现 @hasRole 指令。以下是一个示例 Node.js 代码片段,用于实现 @hasRole 指令:

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

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

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

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

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

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

在上面的代码中,我们使用 SchemaDirectiveVisitor 类来创建自定义指令解析器。在 visitFieldDefinition 方法中,我们获取原始解析器函数并替换它。在新的解析器函数中,我们检查用户是否具有所需的角色,如果没有,则抛出一个错误。

2. 基于权限的授权

除了基于角色的授权之外,还可以使用基于权限的授权来限制用户对数据的访问。在 GraphQL 中,可以使用自定义指令来实现基于权限的授权。

以下是一个示例查询,它使用 @hasPermission 指令来限制只有具有 view_users 权限的用户才能访问用户列表:

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

在服务器端,可以编写自定义指令解析器来实现 @hasPermission 指令。以下是一个示例 Node.js 代码片段,用于实现 @hasPermission 指令:

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

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

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

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

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

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

在上面的代码中,我们使用 SchemaDirectiveVisitor 类来创建自定义指令解析器。在 visitFieldDefinition 方法中,我们获取原始解析器函数并替换它。在新的解析器函数中,我们检查用户是否具有所需的权限,如果没有,则抛出一个错误。

结论

验证和授权是构建 GraphQL API 不可或缺的部分。通过使用 HTTP 头部或 GraphQL 变量进行验证,并使用自定义指令进行授权,我们可以实现强大的安全性和灵活性,以确保用户只能访问他们有权访问的数据。

希望本文能够帮助您更好地理解和应用 GraphQL 中的验证和授权。如果您有任何问题或建议,请随时在评论区留言。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6725c7da2e7021665e18afa5