如何针对 GraphQL 实现服务端数据验证

GraphQL 是一种用于 API 的查询语言和解析器,它允许客户端通过一个简单的查询语句来获取所需的数据,而无需多次交互。GraphQL 的出现,让前端开发者能够更高效地实现数据的获取和处理。但与此同时,GraphQL 也带来了一些数据验证方面的问题。例如,客户端发送的查询语句可能存在垃圾输入、无效输入、数据结构不匹配等问题,这些问题可能会对服务端造成安全隐患或数据损坏。因此服务端数据验证是 GraphQL 开发过程中非常重要的一环。本文将介绍针对 GraphQL 实现服务端数据验证的方法。

为什么需要服务端数据验证?

GraphQL 类似于传统的 RESTful API,但有一些本质上的不同。在 RESTful API 中,客户端只能访问固定的资源,而在 GraphQL 中,客户端能够自由选择所需的数据,并在单个查询中请求多个资源。

这种灵活性可能导致服务端存在一些数据验证方面的风险。在 GraphQL 查询中,客户端可以自由指定查询语句中包含的字段,这意味着客户端可以请求具有不同结构的结果集。在这种情况下,数据结构不匹配问题就可能发生。假设一个查询在服务端返回的结果中需要一个固定结构的数据,但客户端发送的查询却没有包含这个结构,这个问题很明显将导致服务端返回无效数据,从而破坏整个系统的功能。

服务端数据验证的目的就是要验证 GraphQL 查询和变更请求的有效性,以保证服务端系统的安全性和完整性。

如何实现服务端数据验证?

1. 使用工具进行数据验证

常见的一种服务端数据验证方法是使用 数据验证工具 如:Yup、Joi等,在 GraphQL 的 resolvers 中使用这类工具,可以快速、方便、有效地验证 GraphQL 查询所返回的数据结构的正确性。例如,使用 Joi 验证查询是否给定了需要的参数。

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

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

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

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

使用这种方法,在 GraphQL 查询结果不匹配时,我们可以使用错误回调返回明确的错误信息,以帮助使用者更好地理解和排查问题。因此,这种方法是服务器端数据验证的常用方式。

2. 使用 GraphQL 的 Type System 进行数据验证

在 GraphQL 中,Type System 可以用于定义 GraphQL Schema 中的类型,我们可以使用这些类型来验证 GraphQL 查询的有效性。Type System 允许定义数据类型的字段、默认值、输入类型等信息,这些信息可以限制客户端的查询内容。 Type System 提供内置的标量类型,如 ID、String、Int、Boolean 等,也支持自定义类型。

这种方式相较于使用工具验证,有些繁琐,但是与工具相比,Type System 更易于扩展和维护,因此当 Type System 定义好之后,开发者无需再次考虑具体的验证逻辑。

例如,假设我们定义了一个名为 UserList 的自定义类型,它包含 id、name 和 age 字段,那么使用这个自定义类型时,GraphQL Schema 可以定义为类似以下内容:

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

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

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

在这里我们使用 Type System 的 input 和 output 类型限制了请求的参数和响应的结构。当客户端发送请求的结构不符合 GraphQL Schema 定义时,会直接返回错误。这种方式需要在 GraphQL Schema 的编写阶段加入数据验证的相关限制,但当一个开发团队达成一致后,工作量不会很大。

3. 针对字段进行数据验证

从 GraphQL Type System 的优势中我们可以看出,Type System 在验证数据方面具有很高的优势,同时它也可以使用作为第三方数据验证工具来实现,但是使用类型系统有时可能会显得臃肿。

在部分场景下我们也可以针对字段进行验证。这种方式相对于前两种方法,属于较为底层的方法,它需要在 Field Resolver 的实现上执行,这样能够在服务端切入更低层的处理,更好的保证数据的正确性。例如:

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

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

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

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

这种方式是非常灵活和精细的一种方式,但是需要在 Resolver 上添加一些额外的复杂性。

结论

服务端数据验证是 GraphQL 开发过程中必不可少的一部分。在实际应用过程中,数据验证方法可以采用工具验证、Type System 验证或针对字段进行验证等多种方式进行,开发者需要根据实际场景和团队需求来选择不同的验证方法。另外,在实际数据验证过程中,数据验证的粒度应该控制在一个合适的层面,不应过度验证,从而提高效率、减少封装的复杂性。

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