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