后台管理项目

本文介绍了如何使用Node.js创建后台管理项目,包括初始化项目、配置跨域、解析表单数据、用户路由模块的创建,以及实现登录和注册功能。在注册过程中,详细讲解了如何使用bcryptjs加密密码,同时提到了数据验证的重要性,并引入了joi进行表单验证。登录功能的实现包括了JWT Token的生成与验证,确保了接口的安全性。

一、创建项目
1.初始化包管理配置文件:

npm init -y

2.安装espress

npm i express@4.17.1

3.创建app.js作为整个项目的入口文件,导入需要的模块,并启动3007端口

// 导入 express 模块
const express = require('express') 
// 创建 express 的服务器实例 
const app = express() 

// 调用 app.listen 方法,指定端口号并启动web服务器 app.listen(3007, function () { console.log('api server running at http://127.0.0.1:3007') })

4.配置跨域请求,需要用到cors
4.1、安装cors

npm i cors

4.2、在app.js中导入cors中间件,并注册成全局中间件

// 导入 cors 中间件 
const cors = require('cors') 
// 将 cors 注册为全局中间件 app.use(cors())

5、配置解析表单数据的中间件
配置解析 application/x-www-form-urlencoded 格式的表单数据的中间件,默认情况下,如果不配置解析表单数据中间件,则 req.body 默认等于 undefined

app.use(express.urlencoded({ extended: false }))

6、初始化用户路由模块
6.1、创建user.js文件,作为用户的路由模块

const express = require('express') 
const router = express.Router()
// 导入用户路由处理函数模块 
const userHandler = require('../router_handler/user') 
// 注册新用户 
router.post('/reguser', userHandler.regUser) 
// 登录 
router.post('/login', userHandler.login) module.exports = router

6.2、将用户路由的处理函数抽出,目的是为了路由的纯粹性,便于维护
路由的处理函数:


// 注册用户的处理函数 
exports.regUser = (req, res) =>{ 
res.send('reguser OK') 
}
// 登录的处理函数 
exports.login = (req, res) => {
res.send('login OK')
}

二、实现登录和注册的功能
1.在MySQL Workbench 创建用户存储数据表单

2.在项目中安装并且配置MySQL的模块
2.1安装MySQL模块

npm i mysql

2.2、创建新新文件,并且自定义模块中创建数据库的连接对象

// 导入 mysql 模块 
const mysql = require('mysql') 
// 创建数据库连接对象 
const db = mysql.createPool({ 
host: '127.0.0.1', 
user: 'root', 
password: '******', 
database: 'my_db_01', 
})
// 向外共享 db 数据库连接对象 
module.exports = db

3.实现注册功能
3.1检测表单数据是否合法
首先先判断客户端传送来的用户名和密码是否为空

// 接收表单数据 
const userinfo = req.body 
// 判断数据是否合法
if (!userinfo.username || !userinfo.password) {
return res.send({ 
status: 1, 
message: '用户名或密码不能为空!' 
}) 
}

3.2检测用户是否被占用
3.2.1导入数据库的操作模块

const db = require('../db/index')

3.2.2 定义SQL语句,注意?是占位符

const sql = `select * from ev_users where username=?`

3.2.3 执行SQL语句,并且根据返回的结果判断用户名是否被占用

db.query(sql, [userinfo.username], 
function (err, results) { 
// 执行 SQL 语句失败
if (err) { return res.send({ 
status: 1, 
message: err.message
}) } 
// 用户名被占用 
if (results.length > 0) 
{ return res.send({ 
status: 1,
message: '用户名被占用,请更换其他用户名!' 
}) }
// TODO: 用户名可用,继续后续流程... })

如果用户可用,先对用户输入的密码进行一个加密的操作,使用bcryptjs对用户的密码进行加密
优点:
加密之后的密码,无法被逆向破解
同一明文密码多次加密,得到的加密结果各不相同,保证了安全性
3.3 导入bcryptjs

npm i bcryptjs

3.3.1在用户路由的文件,导入bcryptjs

const bcrypt = require('bcryptjs')

3.3.2 在注册用户的处理函数中,确认用户名可用之后,调用 bcrypt.hashSync(明文密码, 随机盐的长度) 方法,对用户的密码进行加密处理:

// 对用户的密码,进行 bcrype 加密,返回值是加密之后的密码字符串
userinfo.password = bcrypt.hashSync(userinfo.password, 10)

4 插入新用户
4.1 定义SQL语句

const sql = 'insert into ev_users set ?'

4.2 执行SQL语句,插入新用户

 db.query(sql,{username:userinfo.username,password:userinfo.password},(err,results) => {
            // 判断sql语句是否执行成功
            // if(err) return res.send({ status:1, message: err.message})
            if(err) return res.cc(err)
            // 判断影响函数是否为一
            // if(results.affectedRows !==1 ) return res.send({status:1, message:'注册用户失败'})
            if(results.affectedRows !==1 ) return res.cc('注册用户失败')
            // 注册用户成功
            // res.send({status:0, message:'注册用户成功'})
            res.cc('注册成功')
        })

注册成功的效果:

序号9就是刚刚注册成功的用户

  1. 在处理函数中,需要多次调用 res.send() 向客户端响应 处理失败 的结果,为了简化代码,可以手动封装一个 res.cc() 函数
    5.1 在app.js 中在所有路由之前声明一个全局中间件,对res对象挂载一个res.cc()函数
// 封装一个res.cc函数,用于每次如果有错误都会执行一次,便于复用
app.use((req,res,next) => {
    // status默认值为1,
    res.cc = function(err,status = 1){
        res.send({
            status,
            message:err instanceof Error ? err.message:err
        })
    }
    next()
})

6.优化表单的数据认证
单纯的使用 if...else... 的形式对数据合法性进行验证,效率低下、出错率高、维护性差。因此,推荐使用第三方数据验证模块,来降低出错率、提高验证的效率与可维护性

6.1可以使用安装 joi 包,为表单中携带的每个数据项,定义验证规则
安装 @escook/express-joi中间件,来实现自动对表单数据进行验证的功能

npm install @hapi/joi@17.1.0,joi

6.2创建验证规则的文件user.js

// 导入验证规则的包
const joi = require('joi')
// 定义用户名和密码的验证规则
// string必须是字符串,alphanum只包含a-z,A_Z,0——9; min最小长度,max最大长度,required必填项,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
    }
}

7.注册新用户的代码优化如下:

// 1.导入验证表单的中间件
const expressjoi = require('@escook/express-joi')
// 2.导入需要验证规则对象
const {reg_login_schema} = require('../schemn/user')
// 注册用户 并且调用验证规则的对象;处理函数
router.post('/reguser',expressjoi(reg_login_schema),use_handle.regUser)

7.在app.js 的全局错误级别中间件中,捕获验证失败的错误,并把验证失败的结果响应给客户端:

// 定义错误的中间件
app.use((err,req,res,next) => {
    if(err instanceof joi.ValidationError) return res.cc(err)
})

8,实现登录功能
8.1.编写登录接口,并且验证表单的数据是否合法

router.post('/login',expressjoi(reg_login_schema),use_handle.login)

8.2.接收表单数据

const userinfo = req.body

8.3.定义SQL语句,根据用户名查询数据

const sql = `select * from ev_users where username=?`

8.4.执行SQL语句


// 执行SQL语句
db.query(sql,userinfo.username,(err,results) => {
    // 执行SQL失败
    if(err) return res.cc(err)
    // 执行SQL语句成功,但是获取的数据条数不等于1
    if(results.length !==1) return res.cc('登录失败')
    //TODO 成功之后的操作
})

8.5.成功执行之后,需要验证客户端传过来的密码是否正确
核心实现思路:调用 bcrypt.compareSync(用户提交的密码, 数据库中的密码) 方法比较密码是否一致,
返回值是布尔值(true 一致、false 不一致)

    const compareResult = bcrypt.compareSync(userinfo.password,results[0].password)
    if(!compareResult) return res.cc("登录失败,密码错误")
// TODO:登录成功,生成 Token 字符串

8.6.创建 config.js 文件,并向外共享加密和还原 Token 的 jwtSecretKey 字符串

module.exports = {
  // 加密和解密token的密钥
  jwtSecretKey:'bee like qianduan #',
//   token的有效期
expiresIn:'10h'
}

8.7生成token字段,核心注意点:在生成 Token 字符串的时候,一定要剔除密码和头像的,密码过于重要不建议放在token里面,而头像的字段过于太大,也不适合放入token字段

 // 生成Token字符串 剔除密码和头像
    // 1.获取用户信息,剔除重要信息
    const user = {...results[0],password:'',user_pic:''}
    // 2.对用户信息进行加密,生成Token字段
    const tokenStr = jwt.sign(user,config.jwtSecretKey,{expiresIn:config.expiresIn})
    // 3.调用res.send 将token响应给客户端
    res.send({
        status:0,
        message:'登录成功',
        token:  'Bearer ' + tokenStr
    })

实现的效果图:


登录成功之后,返回了一段token字段,注意设置的token有效期为10小时,用于登录有权限的接口

9.配置解析token的中间件
9.1安装解析token的中间件

npm i express-jwt

9.2需要在路由前,设置一个解析token的中间件

// 在路由之前配置解析的token中间件
const expressJWT = require('express-jwt')
const config = require('./config')
// 注册成全局中间件 设置除了api以外的接口都需要token认证
app.use(expressJWT({secret:config.jwtSecretKey}).unless({path:[/^\/api/]}))

9.3在app.js 中的错误级别中间件里面,捕获并处理 Token 认证失败后的错误:

// 捕获身份认证失败的错误 
if (err.name === 'UnauthorizedError') return res.cc('身份认证失败!')

接入有权限接口的时候效果图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值