koa中使用joi进行参数校验

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了koa中使用joi进行参数校验相关的知识,希望对你有一定的参考价值。

参考技术A

在编写api的时候通常都需要对参数进行校验,包括参数的类型、必填等;如果是字符串,是否可以为空、该符合什么规则等;如果是数字,最大值最小值是什么等等等等。
在koa中我推荐使用 joi 这个库来进行参数校验。 joi文档

安装: npm install joi --save
引入: import Joi from \'joi\'

下面来看看joi的用法:

使用 joi 进行校验,首先要定义它的校验规则,也叫 schema

上面就定义了一个校验字符串类型的规则,这个 schema 会有一个 validate 方法,传入需要校验的值:

validate 方法会返回一个对象,如果验证通过,就只会返回 value 属性,如果验证错误,就还有一个 error 对象,其中 error 对象的 message 描述了失败原因:

既然是对koa的接口进行参数校验,无论是 ctx.request.query 还是 ctx.request.body 都是对象,那么使用 joi 校验基本都是对象校验了。

与上面验证string一样,都是定义一个schema:

其实就是在object中组合嵌套其他规则,顺便解释下上面几个规则:

name: Joi.string().allow(\'\').required()
代表着name属性为必填,而且可以支持空字符串, Joi.string() 默认情况不支持空字符串。

age: Joi.number().min(18).max(35)
代表age属性需要是一个数字,且最小为18最大为35

skill: Joi.array().items(Joi.string()).length(3)
代表skill属性为一个数组且数组长度为3且都得是字符串

其中age和skill没有设置 required ,可以不填,但是填了的话就必须按照上面的规则。
而且这个对象不能存在其他属性,如果需要允许其他属性的出现,需要在跟上一个 unknown 方法:

有些情况某个字段的校验规则是根据另一个字段来规定的。

a属性表示是个数组,且为number类型,并且只允许18、35这两个值当中二选一,也就是上面的 valid 方法。
b属性表示必须为a属性其中的一项。

使用 ref 可以指向其他属性,需要填写上属性名,然后可以指定在哪一层对象中寻找指向的属性,也就是上面的 ancestor: 1 ,不写的情况也就是上面例子中的 b.c ,会在当前对象中寻找,等同于写上 ancestor: 1 , ancestor: 2 代表在上一层对象中寻找,如果找不到就会验证失败。
所以上面的例子就是 a 属性为 /^[1-9][0-9]*$/ 正则校验通过的字符串,b为对象, b.c 可以为任何类型, b.d 要求与 b.c 一致, b.e 也要求与 b.c 一致, b.f 要求与外面的 a 属性一致。

使用with表示当设置的属性有一个出现了,其他也必须出现,上面的例子设置了a、b属性,需要同时存在或者同时不存在。

without第一个参数设置条件字段,第二个参数为字段数组,表示第一个参数字段存在的话,第二个参数数组里面的字段都不能存在。上面的例子就是当 a 字段出现时, b 字段就不能存在。

xor表示设置的参数需要任何一个或多个存在。

when相当于条件判断,第一个参数传递属性名, is 相当于 if , then 后面就是 is 为真的时候的校验条件。
所以上面的例子就是mode字段只允许传入\'email\'和\'phone\',当mode字段为\'email\'的时候,address字段就会进行email校验(joi自带的字符串邮箱校验)。

先看看文件结构:

既然是接口校验,那么校验的文件跟路由文件对应,每个中间件单独一个文件。

先看validator下的user文件:

定义了一个添加用户的接口参数校验,其中的createTime代表着毫秒时间戳,不能超过当前时间。

接下来看一下middlewares下的validateParams中间件:

因为koa的中间件参数固定为ctx与next,所以这里设计成一个工厂模式,可以将具体的schema传递进来。约定get方法参数传递在 ctx.request.query ,其他方法参数传递在 ctx.request.body ,对参数对象进行校验。

最后看一下路由:

在进入主逻辑之前先走一遍参数校验,传递校验规则schema与method。
下面用postman模拟一下这个接口请求:

校验成功:

校验失败:

用joi这个插件来做参数校验还是非常nice的,超人鸭之前使用过 ajv ,但是文档比较难看懂,所以这次尝试了joi。

我是鸭子,祝你幸福。

更简洁的参数校验,使用 FluentValidation 对参数进行校验

在开发接口时,如果要对参数进行校验,你会怎么写?编写 if-else 吗?虽然也能达到效果,但是不够优雅。今天,推荐一种更简洁的写法,使用 FluentValidation 对方法参数进行校验,特别是在编写 Controller 层的方法时,直接使用一个注解即可完成参数校验。

FluentValidation 是一个使用 Linq 表达式,非常流畅的小型业务对象验证组件。流畅也可以说优雅。类似链式操作。易于理解,功能完善。还可以配合 MVC 使用直接在页面进行验证,当你看到它的语法时,非常优雅,非常令人心动。

  1. 在控制器中使用[Required]和[StringLength]特性标记:

public class User



    [Required]

    public string Name  get; set; 



    [StringLength(20)]

    public string Password  get; set; 





public class UserController : Controller



    public IActionResult Create([FromBody] User user)

    

        // to do

    

  1. 使用ModelState.IsValid方法进行参数校验:

public IActionResult Create([FromBody] User user)



    if (ModelState.IsValid)

    

        // to do

    

    else

    

        // to do

    

  1. 使用FluentValidation库进行参数校验:

public class UserValidator : AbstractValidator<User>



    public UserValidator()

    

        RuleFor(user => user.Name).NotEmpty();

        RuleFor(user => user.Password).Length(6, 20);

    





public class UserController : Controller



    private readonly IValidator<User> _validator;



    public UserController(IValidator<User> validator)

    

        _validator = validator;

    



    public IActionResult Create([FromBody] User user)

    

        if (_validator.Validate(user).IsValid)

        

            // to do

        

        else

        

            // to do

        

    

在实际开发中,我们可以使用 FluentValidation提供的注解进行参数校验,提高代码的可读性,避免编写大量的 if-else 代码块和重复的校验语句。

以上是关于koa中使用joi进行参数校验的主要内容,如果未能解决你的问题,请参考以下文章

低代码中的表单校验工具joi使用方法

api服务器思路

更简洁的参数校验,使用 FluentValidation 对参数进行校验

Java中的参数校验

Java中的参数校验

Spring Boot参数校验以及分组校验的使用