Node.js 》》数据验证 Joi 、express-joi

express-joi、joi

 joi是nodej的一个工具模块,主要用于JavaScript对象的校验。它是一种简单易用的javacript对象约束描述语言,可以轻松解决nodejs开发中的各种参数的校验。
 1. string()    			    值必须是字符串
 2. alphanum()   				值只能包含a-zA-Z的字符串
 3. min(n)       				最小长度
 4. max(n)       				最大长度
 5. required    			    值必填项,   不能为  undefined
 6. pattern(正则表达式)           值必须符号正则表达式
express-joi 是一个基于 Joi 的中间件,用于在 Express 应用中进行参数验证。它可以帮助我们验证请求中的 body、query 和 params 数据,确保数据的有效性和安全性。
#  安装
		npm install @escook/express-joi
		npm install joi
#  导入
        const express = require('express');
		const app = express();
		const Joi = require('joi');
		const expressJoi = require('@escook/express-joi');	
# 定义验证规则
		const userSchema = {
			body: {
				username: Joi.string().alphanum().min(3).max(12).required(),
				password: Joi.string().pattern(/^[\S]{6,15}$/).required(),
				repassword: Joi.ref('password')
			},
			query: {
				name: Joi.string().alphanum().min(3).required(),
				age: Joi.number().integer().min(1).max(100).required()
			},
			params: {
				id: Joi.number().integer().min(0).required()
			}
		}
# 使用中间件进行验证  
        // 数据验证通过之后,会把这次请求流转给后面的路由处理函数
        // 数据验证失败 ,  终止后续代码执行,并抛出一个 全局Error 错误,进入全局错误中间件中
		app.post('/adduser/:id', expressJoi(userSchema), function(req, res) {
		const body = req.body;
		res.send(body);
		})
# 错误处理
     app.use(function(err, req, res, next) {
		if (err instanceof Joi.ValidationError) {
		return res.send({ status: 1, message: err.message });
		}
		res.send({ status: 1, message: err.message });
	})
# 启动服务
    app.listen(3001, function() {
	 console.log('Express server running at http://127.0.0.1:3001');
	})

案例

》》》创建验证规则文件 (schema/user.js)

// schema/user.js
const joi = require('joi')

// 用户注册和登录表单的验证规则
const username = joi.string().alphanum().min(3).max(12).required()
const password = joi
  .string()
  .pattern(/^[\S]{6,15}$/)
  .required()
const email = joi.string().email().required()

// 注册和登录表单的验证规则对象
exports.reg_login_schema = {
  // 表示对 req.body 中的数据进行验证
  body: {
    username,
    password,
    email
  }
}

// 更新用户信息验证规则
exports.update_userinfo_schema = {
  body: {
    id: joi.number().integer().min(1).required(),
    nickname: joi.string().required(),
    email: joi.string().email().required()
  }
}

// 更新密码验证规则
exports.update_password_schema = {
  body: {
    oldPwd: password,
    newPwd: joi.not(joi.ref('oldPwd')).concat(password)
  }
}

// 更新头像验证规则
exports.update_avatar_schema = {
  body: {
    avatar: joi.string().dataUri().required()
  }
}

》》创建路由文件 (routes/user.js)

// routes/user.js
const express = require('express')
const router = express.Router()
const expressJoi = require('@escook/express-joi')
//  路由处理模块
const userHandler = require('../handler/user')
const { 
  reg_login_schema,
  update_userinfo_schema,
  update_password_schema,
  update_avatar_schema
} = require('../schema/user')

// 注册新用户
router.post('/register', expressJoi(reg_login_schema), userHandler.register)

// 登录
router.post('/login', expressJoi(reg_login_schema), userHandler.login)

// 更新用户基本信息
router.post('/userinfo', expressJoi(update_userinfo_schema), userHandler.updateUserInfo)

// 重置密码
router.post('/updatepwd', expressJoi(update_password_schema), userHandler.updatePassword)

// 更新头像
router.post('/update/avatar', expressJoi(update_avatar_schema), userHandler.updateAvatar)

module.exports = router

》》创建控制器文件 (handler/user.js)

// handler/user.js
exports.register = (req, res) => {
  // 这里的 req.body 数据已经通过验证
  res.send({
    status: 0,
    message: '注册成功!',
    data: req.body
  })
}

exports.login = (req, res) => {
  res.send({
    status: 0,
    message: '登录成功!',
    data: req.body
  })
}

exports.updateUserInfo = (req, res) => {
  res.send({
    status: 0,
    message: '更新用户信息成功!',
    data: req.body
  })
}

exports.updatePassword = (req, res) => {
  res.send({
    status: 0,
    message: '更新密码成功!',
    data: req.body
  })
}

exports.updateAvatar = (req, res) => {
  res.send({
    status: 0,
    message: '更新头像成功!',
    data: req.body
  })
}

》》创建主应用文件 (app.js)

// app.js
const express = require('express')
const app = express()

// 配置解析表单数据的中间件
app.use(express.urlencoded({ extended: false }))
app.use(express.json())

// 导入并注册用户路由模块
const userRouter = require('./routes/user')
app.use('/api', userRouter)

// 错误中间件
app.use((err, req, res, next) => {
  // 数据验证失败
  if (err instanceof joi.ValidationError) {
    return res.send({
      status: 1,
      message: err.message
    })
  }
  // 未知错误
  res.send({
    status: 1,
    message: err.message
  })
})

// 启动服务器
app.listen(3000, () => {
  console.log('server running at http://127.0.0.1:3000')
})

高级验证案例

》》自定义验证消息

// schema/user.js
exports.reg_login_schema = {
  body: {
    username: joi.string().alphanum().min(3).max(12).required()
      .messages({
        'string.base': '用户名必须是字符串',
        'string.alphanum': '用户名只能包含字母和数字',
        'string.min': '用户名长度不能小于3',
        'string.max': '用户名长度不能大于12',
        'any.required': '用户名是必填项'
      }),
    password: joi
      .string()
      .pattern(/^[\S]{6,15}$/)
      .required()
      .messages({
        'string.base': '密码必须是字符串',
        'string.pattern.base': '密码长度6-15位,不能包含空格',
        'any.required': '密码是必填项'
      })
  }
}

》》条件验证

// schema/user.js
exports.update_userinfo_schema = {
  body: {
    id: joi.number().integer().min(1).required(),
    nickname: joi.string().required(),
    email: joi.string().email().required(),
    // 只有 is_vip 为 true 时才需要验证 vip_expire 字段
    is_vip: joi.boolean(),
    vip_expire: joi.when('is_vip', {
      is: true,
      then: joi.date().required(),
      otherwise: joi.optional()
    })
  }
}

》》数组验证

// schema/product.js
const joi = require('joi')

exports.add_product_schema = {
  body: {
    name: joi.string().required(),
    price: joi.number().min(0).required(),
    // 验证数组
    tags: joi.array().items(
      joi.string().valid('新品', '热销', '折扣')
    ).min(1).required(),
    // 验证对象数组
    specs: joi.array().items(
      joi.object({
        name: joi.string().required(),
        value: joi.string().required()
      })
    ).min(1).required()
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值