Joi验证时能否用原始入参data替代validate返回的value使用?
关于Joi验证中原始入参data与返回value的差异说明
核心结论:不能直接用原始入参data替代Joi返回的value,二者并不始终一致,直接用data的用法不合规也存在安全风险
二者存在差异的核心原因
Joi的验证逻辑不只是做格式校验,还会执行大量你配置的隐式转换逻辑,这些转换只会作用在返回的value上,不会修改原始入参data。常见会触发差异的配置包括:
- 默认值填充:如果schema配置了
default(),未传的字段会在value里补默认值,原始data里不会有这个字段 - 类型转换:比如schema定义是
Joi.number(),你传的data里对应字段是字符串格式的数字"123",Joi验证通过后会在value里转成数字类型123,原始data里还是字符串 - 数据修剪:比如字符串配置了
trim(),value里会去掉前后空格,原始data还是带空格的原值 - 自定义转换:你通过
custom()/alter()等方法写的自定义转换逻辑,只会修改返回的value,不会动原始入参 - 未知字段过滤:如果schema配置了
unknown(false)(Joi默认配置),原始data里未在schema中定义的字段会被过滤掉,value里不会出现这些字段,原始data里还是保留的
两种写法的正确处理方式
- 官方推荐的
joi.validate()写法
const { error, value } = Joi.validate(data, schema) if (!error) { // 必须用value做后续逻辑,不要用data }
- try/catch包装的断言式写法
你可以把value的定义提到try块外面,或者直接把后续逻辑都放到try块里,不要绕去用原始data:
let validValue try { validValue = await Joi.assert(data, schema) // 或者后续逻辑直接写在这里,直接用返回的value } catch (err) { // 错误处理逻辑 } // 外部用validValue即可
直接用data的风险
- 类型不匹配引发后续逻辑报错,比如本该是数字的字段还是字符串,做计算的时候出问题
- 漏了默认值导致业务逻辑异常,比如配置了默认状态是1,你用原始data拿不到这个字段,判断成未传值出错
- 多余的未知字段引入安全问题,比如用户传了未定义的权限字段,你没过滤就用了,导致越权问题
内容的提问来源于stack exchange,提问作者Merouane
相关产品推荐
相关产品推荐

