开发文档
http://escook.cn:8088
优化
在处理函数中,需要多次调用 res.send() 向客户端响应 处理失败 的结果,
为了简化代码,可以手动封装一个 res.cc() 函数
在 app.js 中,所有路由之前,声明一个全局中间件,
为 res 对象挂载一个 res.cc() 函数 :
// 响应数据的中间件
app.use(function (req, res, next) {
// status = 0 为成功; status = 1 为失败; 默认将 status 的值设置为 1,
方便处理失败的情况
res.cc = function (err, status = 1) {
res.send({
// 状态
status,
// 状态描述,判断 err 是 错误对象 还是 字符串
message: err instanceof Error ? err.message : err,
})
}
next()
})
第三方包
npm install express
跨域
npm install cors
数据库
npm install mysql
密码加密
npm install bcryptjs
npm install jwt
npm install jsonwebtoken
解析token
npm install express-jwt
目录
app.js
const express = require("express");
const app = express();
/**
* 中间件位置
**/
//1.配置跨域
const cors = require("cors");
app.use(cors());
//配置解析表单数据的中间件
app.use(
express.urlencoded({
extended: false,
})
);
//配置响应数据中间件
app.use((req, res, next) => {
// @ts-ignore
res.cc = (err, status = 1) => {
res.send({
status: status,
message: err instanceof Error ? err.message : err,
});
};
next();
});
//配置解析token的中间件
const { expressjwt } = require("express-jwt");
const config = require("./config");
// @ts-ignore
app.use(
expressjwt({
secret: config.jwtScretKey,
algorithms: ["HS256"],
}).unless({
path: [/^\/api\//],
})
);
// 路由位置
const userRouter = require("./router/user");
app.use("/api", userRouter);
//定义错误级别的中间件
const joi = require("@hapi/joi");
app.use((err, req, res, next) => {
console.log(err);
if (err instanceof joi.ValidationError) res.cc(err);
if (err.name === "UnauthorizedError") return res.cc("身份验证失败");
//未知错误
res.cc(err);
});
//启动服务器
app.listen(3000, () => {
console.log("服务器已启动》》》》");
});
router下的路由包
user.js
const express = require('express')
const router = express.Router()
const userHandler = require("../router_handler/user")
//导入验证数据的中间件
const expressJoi = require('@escook/express-joi')
//导入需要验证的规则对象
const { reg_login_schema } = require('../schema/user')
//注册新用户
router.post('/reguser', expressJoi(reg_login_schema), userHandler.regUser)
//用户登录
router.post('/login', expressJoi(reg_login_schema), userHandler.login)
//将路由对象导出
module.exports = router
路由的实现函数包
const db = require('../db/index')
//导入密码加密
const bcrypt = require('bcryptjs')
//导入生成token的包
const jwt = require('jsonwebtoken')
//导入密钥
const config = require('../config')
//注册新用户功能
exports.regUser = (req, res) => {
console.log(req.body)
//接受表单数据
const userinfo = req.body
//1.检测表单数据是否合法
if (!userinfo.username || !userinfo.password) {
return res.cc("账号或密码不能为空!!!")
// res.send({
// status: 1,
// message: "账号或密码不能为空!!!"
// })
}
//2.检测用户是否存在
const sqlStr = 'select * from ev_users where username=?'
db.query(sqlStr, userinfo.username, (err, results) => {
if (err) return res.cc(err)
// res.send({
// status: 1,
// message: err.message
// })
if (results.length > 0) {
return res.cc("用户名被占用,请更换其他用户名!")
// res.send({
// status: 1,
// message: "用户名被占用,请更换其他用户名!"
// })
}
})
//3.密码加密
userinfo.password = bcrypt.hashSync(userinfo.password, 10)
//4.添加用户
const insertUserSql = 'insert into ev_users set ?'
db.query(insertUserSql, {
username: userinfo.username,
password: userinfo.password
}, (err, results) => {
if (err) return res.cc(err)
// res.send({
// status: 1,
// message: err.message
// })
if (results.affectedRows !== 1) {
return res.cc("注册失败")
// res.send({
// status: 1,
// message: "注册失败"
// })
}
res.cc("注册成功", 0)
// res.send({
// message: "ok"
// })
})
}
exports.login = (req, res) => {
//1.检测表单数据是否合法
//2.根据用户名查询用户的数据
const userinfo = req.body
console.log(userinfo)
const sql = 'select * from ev_users where username=?'
db.query(sql, userinfo.username, (err, results) => {
if (err) return res.cc(err)
if (results.length !== 1) return res.cc("登录失败")
//判断用户输入的密码与数据库中的密码是否一样
console.log(results)
const compareResult = bcrypt.compareSync(userinfo.password, results[0].password)
if (!compareResult) return res.cc("密码错误")
//4.生成JWT的token字符串
const user = {...results[0], password: '', user_pic: '' }
console.log(user)
const tokenStr = jwt.sign(user, config.jwtScretKey, { expiresIn: config.expirseIn })
//响应数据
res.send({
status: 0,
message: "登录成功!",
token: 'Bearer' + tokenStr
})
})
}