node.js(express.js)+mysql注册代码优化

发布时间:2024年01月17日

(一)未优化前的代码

实现步骤

一、获取客户端提交到服务器的用户信息,对表单中的数据,进行合法性的效验 代码如下:

// 注册新用户的接口
exports.regUser = (req, res) => {
  // 获取客户端提交到服务器的用户信息
  const userinfo = req.body;
  // 对表单中的数据,进行合法性的效验,如果有一项为空
  if (!userinfo.username || !userinfo.password) {
    return res.send({
      status: 1,
      message: "用户名或密码不合法",
    });
  }
  console.log(userinfo);
};

二、检测用户名是否被占用

/utils/db.js文件的代码如下:

const mysql = require("mysql");
const db = mysql.createPool({
  host: "localhost", // 连接地址
  port: "3306", //端口号
  user: "root", //用户名XXXXXXXX
  password: "XXXXXXXX", //密码
  database: "exapp2", //数据库名
});
module.exports = db;
var db = require("../utils/db");
// 注册新用户的接口
exports.regUser = (req, res) => {
  // 获取客户端提交到服务器的用户信息
  const userinfo = req.body;
  // 对表单中的数据,进行合法性的效验,如果有一项为空
  if (!userinfo.username || !userinfo.password) {
    return res.send({
      status: 1,
      message: "用户名或密码不合法",
    });
  }
   // 检验用户名是否被占用
  // 定义sql语句,查询用户名是否被占用
  var sql = `select * from ev_users where username=?`;
  db.query(sql, userinfo.username, (err, data) => {
    // 执行sql语句失败,
    if (err) {
      return res.send({
        status: 1,
        message: err.message,
      });
    }
    // 判断用户名是否被占用,data.length 大于0说明sql语句查到了该用户名,所以已定被占用
    if (data.length > 0) {
      // console.log("用户名被占用吗,请更换其他用户名");
      return res.send({
        status: 1,
        message: "用户名被占用吗,请更换其他用户名",
      });
    }
    //  res.send("ok");
  });
  console.log(userinfo);
};

三、对密码进行加密

项目安装指定版本bcryptjs库

 npm i bcryptjs@2.4.3
var db = require("../utils/db");
// 导入密码加密
const bcrypt = require("bcryptjs");
// 注册新用户的接口
exports.regUser = (req, res) => {
  // 获取客户端提交到服务器的用户信息
  const userinfo = req.body;
  // 对表单中的数据,进行合法性的效验,如果有一项为空
  if (!userinfo.username || !userinfo.password) {
    return res.send({
      status: 1,
      message: "用户名或密码不合法",
    });
  }
   // 检验用户名是否被占用
  // 定义sql语句,查询用户名是否被占用
  var sql = `select * from ev_users where username=?`;
  db.query(sql, userinfo.username, (err, data) => {
    // 执行sql语句失败,
    if (err) {
      return res.send({
        status: 1,
        message: err.message,
      });
    }
    // 判断用户名是否被占用,data.length 大于0说明sql语句查到了该用户名,所以已定被占用
    if (data.length > 0) {
      // console.log("用户名被占用吗,请更换其他用户名");
      return res.send({
        status: 1,
        message: "用户名被占用吗,请更换其他用户名",
      });
    }
    // 用户名可以使用,对密码进行加密
    // bcrypt.hashSync(客户端明文密码,10) // 第二个参数提高密码的安全性
    userinfo.password = bcrypt.hashSync(userinfo.password, 10);
    //console.log("@", userinfo.password);
    //  res.send("ok");
  });
  console.log(userinfo);
};

四、插入新用户(完整代码)

var db = require("../utils/db");
// 导入密码加密
const bcrypt = require("bcryptjs");
// 注册新用户的接口
exports.regUser = (req, res) => {
  // 获取客户端提交到服务器的用户信息
  const userinfo = req.body;
  // 1.对表单中的数据,进行合法性的效验,如果有一项为空
  if (!userinfo.username || !userinfo.password) {
    return res.send({
      status: 1,
      message: "用户名或密码不合法",
    });
  }
   // 2.检验用户名是否被占用
  // 定义sql语句,查询用户名是否被占用
  var sql = `select * from ev_users where username=?`;
  db.query(sql, userinfo.username, (err, data) => {
    // 执行sql语句失败,
    if (err) {
      return res.send({
        status: 1,
        message: err.message,
      });
    }
    // 判断用户名是否被占用,data.length 大于0说明sql语句查到了该用户名,所以已定被占用
    if (data.length > 0) {
      // console.log("用户名被占用吗,请更换其他用户名");
      return res.send({
        status: 1,
        message: "用户名被占用吗,请更换其他用户名",
      });
    }
    // 3.用户名可以使用,对密码进行加密
    // bcrypt.hashSync(客户端明文密码,10) // 第二个参数提高密码的安全性
    userinfo.password = bcrypt.hashSync(userinfo.password, 10);
    // 4.插入新用户
    // 定义插入新用户的sql语句
    let sql1 = "insert into ev_users set ?";
    // 调用db.query()执行sql语句
    db.query(
      sql1,
      { username: userinfo.username, password: userinfo.password,},
      function (err, data) {
        // 判断sql语句是否执行成功
        if (err) {
          return res.send({ status: 1, message: err.message });
        }
        // 判断影响行数是否为1
        if (data.affectedRows !== 1) {
          return res.send({ status: 1, message: "注册用户失败,请稍后再试" });
        }
        //注册成功
        res.send({ status: 0, message: "注册成功!" });
      }
    );
    //  res.send("ok");
  });
  console.log(userinfo);
};

在这里插入图片描述

(二)优化后的代码

1. 在上面的代码的基础上封装res.send()方法为统一的中间件,在app.js文件中

// 一定要在路由之前封装res.cc函数
app.use((req, res, next) => {
  // status 默认值 1,表示失败的情况
  // err的值,可能时一个错误对象,也可能时以个错误的描述字符串
  res.cc = function (err, status = 1) {
    res.send({
      status,
      message: err instanceof Error ? err.message : err,
    });
  };
  next();
});

然后在注册接口中把res.send修改成统一res.cc,代码如下:

var db = require("../utils/db");
// 导入密码加密
const bcrypt = require("bcryptjs");

// res.cc是在app.js封装的中间件
// 注册新用户的接口
exports.regUser = (req, res) => {
  // 获取客户端提交到服务器的用户信息
  const userinfo = req.body;
  // 对表单中的数据,进行合法性的效验,如果有一项为空
    if (!userinfo.username || !userinfo.password) {
      return res.send({
        status: 1,
        message: "用户名或密码不合法",
      });
    }
  // 检验用户名是否被占用
  // 定义sql语句,查询用户名是否被占用
  var sql = `select * from ev_users where username=?`;
  db.query(sql, userinfo.username, (err, data) => {
    // 执行sql语句失败,
    if (err) {
      //   return res.send({
      //     status: 1,
      //     message: err.message,
      //   });
      return res.cc(err);
    }
    // 判断用户名是否被占用,data.length 大于0说明sql语句查到了该用户名,所以已定被占用
    if (data.length > 0) {
      // console.log("用户名被占用吗,请更换其他用户名");
      //   return res.send({
      //     status: 1,
      //     message: "用户名被占用吗,请更换其他用户名",
      //   });
      return res.cc("用户名被占用吗,请更换其他用户名");
    }
    // 用户名可以使用,对密码进行加密
    // console.log("@@", userinfo.password);
    // bcrypt.hashSync(客户端明文密码,10) // 第二个参数提高密码的安全性
    userinfo.password = bcrypt.hashSync(userinfo.password, 10);
    console.log("@", userinfo.password);

    // 定义插入新用户的sql语句
    let sql1 = "insert into ev_users set ?";
    // const sqlNewUser = "insert into ev_users set ?";
    // 调用db.query()执行sql语句
    db.query(
      sql1,
      { username: userinfo.username, password: userinfo.password },
      function (err, data) {
        // 判断sql语句是否执行成功
        if (err) {
          //   return res.send({ status: 1, message: err.message });
          return res.cc(err);
        }
        // 判断影响行数是否为1
        if (data.affectedRows !== 1) {
          //   return res.send({ status: 1, message: "注册用户失败,请稍后再试" });
          return res.cc("注册用户失败,请稍后再试");
        }
        //注册成功
        res.cc("注册成功", 0);
        // res.send({ status: 0, message: "注册成功!" });
      }
    );

    //  res.send("ok");
  });
  console.log(userinfo);
};


2. 优化username,password 表单数据验证
在实际开发中,前后端都需要对表单的数据进行合法性的验证,而且,后端做为数据合法性验证的最后一个关口,在拦截非法数据方面,起到了至关重要的作用。
单纯的便用 if…else… 的形式对数据合法性进行验证,效率低下、出错率高、维护性差。因此,推荐便用第三方数据验证模块,来降低出错率、提高验证的效率与可维护性,让后端程序员把更多的精力放在核心业务逻辑的处理上.

(1).安装 jOi 包,为表单中携带的每个数据项,定义验证规则:
npm install joi
(2).安装 @escook/express-j01 中间件,来实现自动对表单数据进行验证的功能:
npm install @escook/express-joi
(3).新建schema/user.js
// 导入定义验证规则的包
// const joi = require("@hapi/joi");
const joi = require("joi");
/**
 * string()值必须是字符串
 * alphanum()值只能包含a-zA-ZO-9的字符串
 * min(length) 最小长度
 * max(length) 大长度
 * required() 值是必填项,不能为 undefined
 * pattern(正则表达式) 值必须符合正则表达式的规则
 */

// 定义用户名和密码的验证规则
const username = joi.string().alphanum().min(1).max(10).required();
const password = joi
  .string()
  .pattern(/^[\S]{6,12}$/)
  .required();
// 定义验证注册和登录表单数据的规则对象
exports.reg_login_schema = {
  body: {
    username,
    password,
  },
};
(4).在routes/use.js中引入schema/user.js中的方法reg_login_schema,代码如下:
var express = require("express");
var router = express.Router();
// 引入封装的获取验证码的方法
var unr_handler = require("../controllers/user");

// 1.导入验证数据的中间件
const expressJoi =require('@escook/express-joi')
//  2.导入需要的验证规则对象
const { reg_login_schema } = require('../schema/user')

// 新用户注册
router.post("/regUser",expressJoi(reg_login_schema), unr_handler.regUser);
// router.post("/regUser", unr_handler.regUser);
// 登录
// router.post("/login", unr_handler.login);
module.exports = router;
(5)在 app.js 的全局错误级别中间件中,捕获验证失败的错误,并把验证失败的结果响应给客户端:
const joi = require('joi')
// 定义表单验证失败的错误的中间件,并把验证失败的结果响应给客户端
// 错误中间件
app.use(function (err, req, res, next) {
  // 数据验证失败,instanceof判断
  if (err instanceof joi.ValidationError) {
    return res.cc(err);
  }
  // 未知错误
  res.cc(err)
});
(6)最终优化后注册接口代码如下:
var db = require("../utils/db");
// 导入密码加密
const bcrypt = require("bcryptjs");

// res.cc是在app.js封装的中间件
// 注册新用户的接口
exports.regUser = (req, res) => {
  // 获取客户端提交到服务器的用户信息
  const userinfo = req.body;
  // 对表单中的数据,进行合法性的效验,如果有一项为空
    // if (!userinfo.username || !userinfo.password) {
    //   return res.send({
    //     status: 1,
    //     message: "用户名或密码不合法",
    //   });
    // }
  // 检验用户名是否被占用
  // 定义sql语句,查询用户名是否被占用
  var sql = `select * from ev_users where username=?`;
  db.query(sql, userinfo.username, (err, data) => {
    // 执行sql语句失败,
    if (err) {
      //   return res.send({
      //     status: 1,
      //     message: err.message,
      //   });
      return res.cc(err);
    }
    // 判断用户名是否被占用,data.length 大于0说明sql语句查到了该用户名,所以已定被占用
    if (data.length > 0) {
      // console.log("用户名被占用吗,请更换其他用户名");
      //   return res.send({
      //     status: 1,
      //     message: "用户名被占用吗,请更换其他用户名",
      //   });
      return res.cc("用户名被占用吗,请更换其他用户名");
    }
    // 用户名可以使用,对密码进行加密
    // console.log("@@", userinfo.password);
    // bcrypt.hashSync(客户端明文密码,10) // 第二个参数提高密码的安全性
    userinfo.password = bcrypt.hashSync(userinfo.password, 10);
    console.log("@", userinfo.password);

    // 定义插入新用户的sql语句
    let sql1 = "insert into ev_users set ?";
    // const sqlNewUser = "insert into ev_users set ?";
    // 调用db.query()执行sql语句
    db.query(
      sql1,
      { username: userinfo.username, password: userinfo.password },
      function (err, data) {
        // 判断sql语句是否执行成功
        if (err) {
          //   return res.send({ status: 1, message: err.message });
          return res.cc(err);
        }
        // 判断影响行数是否为1
        if (data.affectedRows !== 1) {
          //   return res.send({ status: 1, message: "注册用户失败,请稍后再试" });
          return res.cc("注册用户失败,请稍后再试");
        }
        //注册成功
        res.cc("注册成功", 0);
        // res.send({ status: 0, message: "注册成功!" });
      }
    );

    //  res.send("ok");
  });
  console.log(userinfo);
};

文章来源:https://blog.csdn.net/weixin_50379372/article/details/135650531
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。