• nodejs--开发自己的项目—3.2--优化-表单的数据验证——合法性


            表单验证的原则:前端验证为辅,后端验证为主(后端永远不要相信前端提交过来的任何内容

            所以需要对前端提交的数据进行合法性的验证 ,在实际开发中,也需要对后端提交表单数据进行合法性验证(后端做为数据合法性验证的最后一个关口--在数据拦截中起打破了至关重要的作用)——ps不可简单的使用if else对数据进行验证,效率低下、出错率高、维护性差。因此,推荐使用第三方数据验证模块@hapi/joi包——定义验证的规则(客户端向服务器提交的每条数据,都需要定义一个验证规则)@escook/express-joi包——自动对表单数据进行验证()降低出错率、提高验证的效率与可维护性。

       首先安装包:查看说明文档@escook/express-joi - npm

    express中数据分为3种:

    • 一种是表单数据——通过req.body获取
    • 一种是查询字符串数据——通过req.query获取
    • 一种是可以访问到客户端查询字符串形式,发送给服务器参数——通过req.params获取

     定义验证的规则:

    string()——是字符串

    alphanum()——是数字和字母的组合

    min(3)——最小长度max(12)——最大长度

    required()——指定是必传递的参数——如果不传递就会有问题

    pattern——匹配正则表达式

    .ref——指定验证规则的名字

    前拥有的包:注意版本信息


    建立的文件夹中保存验证规则: 

    1. //表单数据验证的包
    2. const joi=require('joi')
    3. //定义验证规则——查看对应文档
    4. //用户名的验证规则
    5. username=joi.string()
    6. .min(1)//最小长度是1
    7. .max(10)//最大长度是10
    8. .required()//所必须传递的字符串
    9. //密码的验证规则
    10. password= joi.string() .pattern(/^[\S]{6,15}$/)
    11. // .pattern(/^[\S]{6,15}$/)//满足自定义正则表达式——且长度为6——12之间\S不能有空字符——
    12. .required()//使用正则表达式
    13. //定义密码重验证的规则
    14. //repeat_password: joi.ref('password'),
    15. module.exports={
    16. body:{//校验body中的数据
    17. username,
    18. password,
    19. }
    20. }

    然后在用户传入表单数据的时候,导入验证表单数据的中间件

    1. //导入express模块
    2. const express=require('express')
    3. //创建路由对象
    4. const Router=express.Router()
    5. //导入处理函数的模块
    6. const user_hander=require('../router_handler/user')
    7. //1、导入验证表单数据的中间件
    8. var expressJoi = require('@escook/express-joi')
    9. const Joi=require('joi')
    10. //2、导入需要验证的规则对象
    11. const schema=require('../schema/user')//存放是是规则_body里面的对象
    12. //挂载具体路由1
    13. //监听客户端注册用户的请求
    14. Router.post('/reguser',expressJoi(schema),user_hander.regUser)
    15. //挂载具体路由2
    16. //监听客户端登录的请求
    17. Router.post('/login',user_hander.login)
    18. //向外导出路由
    19. module.exports=Router//之前={对象 对象里面是属性 可以做一个省略}

    在路由处理函数中 ——对表单数据的验证进行了省略

    1. //对应的路由处理函数
    2. //导入数据库操作模块
    3. const db=require('../db/index')
    4. //检测数据库是否导入成功
    5. // db.query('select 1',(err,results)=>{
    6. // if(err) return console.log(err.message)
    7. // console.log(results)//此结果可以正常打印输出就表示数据库连接正常
    8. // })
    9. //导入bcryptjs包对明文密码进行加密
    10. const bcrypt=require('bcryptjs')
    11. //这是注册新用户的处理函数
    12. const regUser=function(req,res){//postreq.body
    13. //获取客户端提交给服务器的用户信息
    14. const userInfo=req.body
    15. //console.log(userInfo)——测试是否接收到表单数据
    16. //*********对表单中的数据进行合法性的校验_____放到了表单数据传入的部分
    17. //定义SQL语句,查询用户名是否被占用
    18. const sqlStr='select * from ev_users where username=?'//sql语句
    19. db.query(sqlStr,[userInfo.username],(err,results)=>{
    20. //执行SQL语句失败_
    21. if(err) return res.cc(err)
    22. //select查询的结果是数组,用户名被占用——查询不会影响行数
    23. if(results.length>0) return res.cc('用户名被占用,请更换用户名')
    24. //用户名可用使用
    25. //调用bcrypt.hashSync进行加密--归还给userInfo
    26. userInfo.password=bcrypt.hashSync(userInfo.password,10)//加密的内容
    27. //console.log(userInfo)
    28. //定义插入新用户的SQL语句——插入的少使用表(字段)values(值) 插入多使用set
    29. const sqlStr1='insert into ev_users set ?'
    30. db.query(sqlStr1,{username:userInfo.username,password:userInfo.password},(err,results)=>{
    31. //执行SQL语句失败_
    32. if(err) return res.cc(err)
    33. //判断插入失败
    34. if(results.affectedRows!==1)return res.cc('注册用户失败,请稍后再试!')
    35. //c成功传参
    36. res.cc('注册用户成功!',0)
    37. })
    38. })
    39. }
    40. //这是登录的处理函数
    41. const login=function(req,res){//post
    42. res.send('注册OK')//响应给客户端的话
    43. }
    44. //向外暴露
    45. module.exports={
    46. regUser,
    47. login
    48. }

     在主函数模块对出错的验证进行了错误级别中间件进行捕捉,

    1. //导入express模块
    2. const express=require('express')
    3. //创建web服务器
    4. const app=express()
    5. // 导入 cors 中间件——支持跨域访问
    6. const cors = require('cors')
    7. // 将 cors 注册为全局中间件
    8. app.use(cors())
    9. //配置解析application/x-www-form-urlencoded格式数据的内置中间件
    10. app.use(express.urlencoded({ extended: false }))//extended默认值
    11. //导入表单数据中间件
    12. const joi=require('joi')
    13. //在路由之前,封装函数
    14. // 响应数据的中间件
    15. app.use(function (req, res, next) {
    16. // status = 0 为成功; status = 1 为失败; 默认将 status 的值设置为 1,方便处理失败的情况
    17. res.cc = function (err, status = 1) {//status默认失败——传参
    18. res.send({
    19. // 状态
    20. status,
    21. // 状态描述,判断 err 是 错误对象 还是 描述错误字符串
    22. message: err instanceof Error ? err.message : err,//instanceof是否是Error实例
    23. })
    24. }
    25. next()//流转关系传下去
    26. })
    27. //导入并使用用户的路由模块
    28. const userRouter=require('./router/user.js')
    29. app.use('/api',userRouter)//加上统一的前缀——将七注册成为全局可以用的路由模块
    30. //定义错误级别中间件
    31. app.use(function(err, req, res, next) {
    32. if (err instanceof joi.ValidationError) {//验证的方式
    33. return res.cc(err.message)
    34. }
    35. return res.cc('未知的错误')
    36. })
    37. //启动服务器、使用3007端口
    38. app.listen(3007,()=>{
    39. console.log('http://127.0.0.1:3007 服务器启动成功')
    40. })

  • 相关阅读:
    31【window 对象】
    HTML中script 标签中的那些属性
    java学习记录
    Python实现类属性的延迟加载装饰器
    静态代码块
    Redis 会被Dragonfly替代?
    JSP企业内部交流系统myeclipse开发mysql数据库bs框架java编程jdbc
    次氯酸(HClO)荧光探针 激发波长567 nm
    从0开始写中国象棋-创建棋盘与棋子
    电脑病毒感染C卷(Java&&Python&&C++&&Node.js&&C语言)
  • 原文地址:https://blog.csdn.net/weixin_47295886/article/details/126869272