应用系统定制开发(内附源码)Node.js小试——使用Node开发API服务器、登录、注册、加密、表单验证、中间件、异常捕获、JWT认证


文章目录


初始化.js项目

1.创建项目

  1. 应用系统定制开发创建项目文件夹,应用系统定制开发并再项目根目录初始化npm应用系统定制开发包管理文件,以ExpressServer为例,代码如下:
mkdir ExpressServer && cd ExpressServernpm init -y
  • 1
  • 2
  1. 应用系统定制开发应用系统定制开发运行如下命令安装express
npm i express
  • 1
  1. 应用系统定制开发创建项目入口文件,应用系统定制开发并初始化内容如下:
//1. 导入express模块const express = require('express')//2. 创建express应用系统定制开发服务器实例const server = express()// TODO:应用系统定制开发在这里编写服务器代码//3. 应用系统定制开发监听服务器80端口server.listen(80, () => {    console.log('Express server running on http://127.0.0.1:80')})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

2.配置cors跨域

  1. 运行如下命令安装cors中间件:
npm i cors
  • 1
  1. app.js应用系统定制开发中导入并配置cors中间件:
//1. 导入cors中间件const cors = require('cors')//2. 注册cors中间件server.use(cors())
  • 1
  • 2
  • 3
  • 4

3.应用系统定制开发配置数据解析中间件

  1. 应用系统定制开发配置如下代码,解析application/x-www-form-urlencoded格式的表单数据:
server.use(express.urlencoded({ extended: false }))
  • 1

4.初始化路由文件夹

  1. 项目根目录中,创建router文件夹,用于存放所有的路由模块
  2. 项目根目录中,创建router_handler文件夹,用于存放所有的路由处理模块
mkdir router mkdir router_handler
  • 1
  • 2

5.初始化路由模块

  1. router文件夹中新建auth.js,用于存储所有的用户路由,编写内容如下:
const express = require('express')//创建路由对象const router = express.Router()//用户注册路由router.post('/register', (req, res) => {    res.send('POST /register')})//用户登录路由router.post('/login', (req, res) => {    res.send('POST /login')})//共享router对象module.exports = router
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  1. app.js中,导入并注册用户路由模块:
//导入用户路由const authRouter = require('./router/auth')//注册用户路由server.use('/api/auth',authRouter)
  • 1
  • 2
  • 3
  • 4

6.启动并测试服务器

  1. 安装nodemon模块,用于启动服务器(nodemon模块可以在我们修改代码后自动重启服务器):
npm i -g nodemon
  • 1
  1. 使用nodemon模块启动服务器:
nodemon app.js
  • 1

如果操作正确,服务器正常启动,将输出如下内容:

PS E:\ExpressServer> nodemon .\app.js[nodemon] 2.0.16[nodemon] to restart at any time, enter `rs`[nodemon] watching path(s): *.*[nodemon] watching extensions: js,mjs,json[nodemon] starting `node .\app.js`Express server running on http://127.0.0.1:80
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  1. 使用postman测试接口是否配置正确,以POST方式分别访问localhost/api/auth/registerlocalhost/api/auth/login

7.抽离路由处理函数

为了保证路由模块的存粹性,将路由处理函数单独抽离出来放在router_handler文件夹中

  1. router_handler文件夹中创建并编辑auth.js文件如下:
//router_handler/auth.js//注册处理函数exports.authRegister = (req, res) => {    res.send('POST /register')}//登录处理函数exports.authLogin = (req, res) => {    res.send('POST /login')}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  1. 修改/router/auth.js文件代码如下:
//router/auth.jsconst express = require('express')//创建路由对象const router = express.Router()//引入auth处理模块const authHandler = require('../router_handler/auth')//用户注册路由router.post('/register', authHandler.authRegister)//用户登录路由router.post('/login', authHandler.authLogin)//共享router对象module.exports = router
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  1. 使用nodemon启动并使用postman访问localhost/api/auth/registerlocalhost/api/auth/login,会得到和之前(6.3)相同的结果。

注册

1.创建数据库

  1. 创建MySql数据库,此处以db_node为例:
CREATE SCHEMA `db_node` ;
  • 1

如果还没有安装MySql,可以在这里下载

  1. 创建t_users数据表,创建表sql指令如下:
CREATE TABLE `db_node`.`t_users` (  `id` INT NOT NULL AUTO_INCREMENT,  `username` VARCHAR(255) NOT NULL,  `password` VARCHAR(255) NOT NULL,  `nickname` VARCHAR(255) NULL,  `email` VARCHAR(255) NULL,  `avatar` TEXT NULL,  PRIMARY KEY (`id`),  UNIQUE INDEX `id_UNIQUE` (`id` ASC) VISIBLE,  UNIQUE INDEX `username_UNIQUE` (`username` ASC) VISIBLE)ENGINE = InnoDBDEFAULT CHARACTER SET = utf8mb4COLLATE = utf8mb4_0900_ai_ci;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

2.安装并配置mysql模块

  1. 执行如下指令,安装mysql模块:
npm i mysql
  • 1
  1. 创建/db/index.js文件,此文件用于存储数据库连接对象:
// db/index.js//导入mysql模块const mysql = require('mysql')//创建数据库连接对象const db = mysql.createPool({    host: '127.0.0.1',  //数据库服务器地址,我们使用本机    user: 'root',       //mysql用户名,替换为你的用户名    password: '000000', //mysql密码,替换为你的密码    database: 'db_node',//数据库名称,此处为db_node})//导出数据库连接对象module.exports = db 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

3.注册

  1. 注册步骤
  • 检测表单数据
  • 检测用户名是否占用
  • 密码加密处理
  • 插入新用户
  1. 检测表单数据
const userinfo = req.body    if(!userinfo.username || !userinfo.password){        return res.send({            status: 201,            message:'用户名、密码不能为空!'        })    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  1. 检测用户名是否占用
  • db/index.js导入db
const db = require('../db/index')
  • 1
  • 定义SQL
sqlStr = 'select * from t_users where username = ?'
  • 1
  • 执行SQL语句,判断是否占用:
db.query(sql, userinfo.username, (err, results) => {        if (err) return res.send({ status: 201, message: err.message })        if(results.length > 0){            return res.send({status:201,message:'用户名已存在'})        }        //TODO:插入新用户    })
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  1. 密码加密
  • 执行以下指令,安装bcryptjs模块
npm i bcryptjs
  • 1
  • router_handler/auth.js中,导入bcryptjs
const bcrypt = require('bcryptjs')
  • 1
  • 插入用户之前,使用bcrypt.hashSync(password,len)进行加密
userinfo.password = bcrypt.hashSync(userinfo.password,10)
  • 1
  1. 插入用户
  • 定义SQL
sqlStr = 'insert into t_users set ?'
  • 1
  • 执行SQL,插入用户
db.query(sql, { username: userinfo.username, password: userinfo.password }, (err, results) => {            if (err) return res.send({ status: 201, message: err.message })            if (results.affectedRows === 1)                return res.send({ status: 200, message: 'success' })            return res.send({ status: 201, message: '注册失败,稍后再试' })        })
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

4.注册测试

  1. 使用PostMan发送注册信息,操作如下:

  1. 我们可以查看数据库:

如此,注册方法变成功执行了。

优化res.send()

我们在代码中多次使用到了res.send()方法,非常繁琐,需要封装简化代码。(不优化也没啥)

  1. app.js中所有的路由之前定义并注册全局中间件
server.use((req, res, next) => {    //status = 200 success    //status = 201 failure    res.cc = function (err, status = 1) {        res.send({            status: status,            message: err instanceof Error ? err.message : err,        })    }    next()})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

这样在所有的路由中,res都具有一个cc方法,可以方便的向客户端输出结果。

优化

表单验证,前端为辅,后端为主,永远不相信前端提交的数据

1.安装包

1.安装joi包,为表单项定义验证规则

npm i joi
  • 1
  1. 安装@escook/express-joi,实现自动验证表单数据
npm i @escook/express-joi
  • 1

2.验证规则

  1. 新建schema/auth.js用户验证规则模块
mkdir schematouch schema/auth.js
  • 1
  • 2
  1. 初始化如下:
//schema/auth.js//导入包const joi = require('joi')/** * string() 字符串 * alphanum() 字符数字串 * min(len) 最短 * max(len) 最长 * required() 不为空 * pattern(reg) 符合正则 *///用户名密码验证规则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    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

4.插入验证中间件

  1. 引入验证中间件
//引入验证中间件const expressJoi = require('@escook/express-joi') //(*)
  • 1
  • 2
  1. 引入验证规则
//引入验证规则const { reg_login_schema } = require('../schema/auth')//(*)
  • 1
  • 2
  1. 注册验证中间件
//用户注册路由,添加验证中间件router.post('/register', expressJoi(reg_login_schema), authHandler.authRegister) //(*)
  • 1
  • 2

修改后的route/auth.js,如下:

//router/auth.jsconst express = require('express')//创建路由对象const router = express.Router()//引入验证中间件const expressJoi = require('@escook/express-joi') //(*)//引入验证规则const { reg_login_schema } = require('../schema/auth')//(*)//引入auth处理模块const authHandler = require('../router_handler/auth')//用户注册路由,添加验证中间件router.post('/register', expressJoi(reg_login_schema), authHandler.authRegister) //(*)//用户登录路由router.post('/login', authHandler.authLogin)//共享router对象module.exports = router
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

注意以上代码中(*)处是修改的地方。

5.捕获验证错误

app.js中创建并注册全局错误处理中间件,用于处理验证错误(也可以处理其他错误)。

  1. 引入验证规则
//引入验证规则模块const joi = require('joi')
  • 1
  • 2
  1. 创建并注册全局异常中间件
//引入验证规则模块const joi = require('joi')//注册异常捕获中间件server.use((err, req, res, next) => {    if (err instanceof joi.ValidationError) return res.cc(err)    res.cc(err)})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

6.验证测试

登录

1.登录步骤

  1. 表单验证;
  2. 数据查询;
  3. 密码比较;
  4. 生成JWTToken字符串

2.表单验证

  1. 修改router/auth.js的路由如下:
//用户登录路由router.post('/login', expressJoi(reg_login_schema), authHandler.authLogin)
  • 1
  • 2

3.数据查询

router_handler/auth.js中的登录处理方法中:

  1. 表单数据接收
const userinfo = req.body
  • 1
  1. 定义SQL语句
const sqlStr = 'select * from t_users where username=?'
  • 1
  1. 执行查询SQL
//执行查询db.query(sqlStr, userinfo.username, (err, results) => {    //查询失败    if (err) return res.cc(err)    //查询结果不合理    if (results.length !== 1) return res.cc("登录失败")    //TODO:判断密码})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

4.密码比较

调用bcrypt.compreSync(表单密码,数据库密码)判断密码是否一致,true一致,false不一致

//判断密码const cmpRes = bcrypt.compare(userinfo.password, results[0].password)if (!cmpRes) return res.cc('Login Failed')//TODO:登录成功,生成token
  • 1
  • 2
  • 3
  • 4
  • 5

5.生成token

  1. 从查询结果中剔除passwordavatar两个值
const usr = { ...results[0], password: '', avatar: '' }
  • 1
  1. 安装jwt
npm i jsonwebtoken
  • 1
  1. router_handler/auth.js中导入jwt
const jwt = require('jsonwebtoken')
  • 1
  1. 根目录创建配置文件config.js,并共享jwtSecretKey字符串(用于加密)
//config.jsmodule.exports = {    //一个复杂字符串    jwtSecretKey: "alkjflasngaoieakgbnasdfzxfgasdf",    expiresIn: '24h',//token有效期24h}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  1. 加密用户信息,生成token
//导入configconst config = require('../config')//生成tokenconst tokenStr = jwt.sign(usr, config.jwtSecretKey, {            expiresIn: config.expiresIn,//token有效期为24小时})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  1. 返回客户端
res.send({    status: 200,    message: 'login success',    token: 'Bearer ' + tokenStr})
  • 1
  • 2
  • 3
  • 4
  • 5
  1. 测试登录

6.Token解析

  1. 安装express-jwt模块(注意版本,较新版本不适合本教程)
npm i express-jwt@5.3.3
  • 1
  1. app.js中注册路由之前配置Token中间件
const config = require('./config')//导入token中间件const expressJWT = require('express-jwt')//注册token中间件,所有以/api开头的路由都不需要验证token的正确性server.use(expressJWT({ secret: config.jwtSecretKey }).unless({ path: [/^\/api\//] }))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  1. app.jstoken认证失败异常捕捉
if (err.name === 'UnauthorizedError') return res.cc('认证失败')
  • 1
  1. 解析验证

访问非/api开头的路由即可,这里使用/my

想要验证成功,需要在Header中加入Authorization字段,字段的值是登录时返回的Token

获取用户信息

用户中心功能的一部分,获取用户个人信息,使用/my/info路由的GET请求。

1.基本步骤

  1. 初始化个人中心路由“router/my.js”
  2. 初始化路由处理函数“router_handler/my.js”
  3. 获取用户信息

2.初始化/router/my.js

  1. 创建文件router/my.js,编辑代码如下:
// 引入express模块const express = require('express')//创建路由对象const router = express.Router()//挂接/info路由router.get('/info', (req, res) => {    res.send('ok')})//向外分享路由对象module.exports = router
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  1. app.js中导入当前路由模块(可以紧贴/api/auth路由向后写)
//导入路由const myRouter = require('./router/my')//注册/my路由server.use('/my', myRouter)
  • 1
  • 2
  • 3
  • 4

3.测试路由配置

  1. 访问/api/auth/login登录并获取token

复制返回的token字符串。

  1. 访问/my/info

如果你和我的编码相同,返回ok即为正确。

4.初始化/router_handler/my.js

  1. 新建/router_handler/my.js文件,编辑内容如下:
//暴露/my/info路由的处理函数exports.getInfo = (req, res) => {    res.send('/my/info handler')}
  • 1
  • 2
  • 3
  • 4
  1. 修改/router/my.js文件中代码如下:
// 引入express模块const express = require('express')//创建路由对象const router = express.Router()const myHandler = require('../router_handler/my') //(*)//挂接/info路由router.get('/info', myHandler.getInfo)//(*)//向外分享路由对象module.exports = router
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

注意上述代码中(*)处的改动。

  1. 测试路由处理函数

如果返回的内容和我一样就没有问题了。

5.获取用户信息

  1. 导入/db/index模块
const db = require('../db/index')
  • 1
  1. 编写SQL语句
const sql = 'select id,username,nickname,email,avatar from t_users where id=?'
  • 1
  1. 执行查询语句
db.query(sql, req.user.id, (err, results) => {    if (err) return res.cc(err.message)    if (results.length !== 1) return res.cc('获取用户信息失败')    res.send({        status: 200,        message: 'Success',        data: results[0]    })});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

6.测试

这样就执行成功了。

更新用户信息

使用/my/infoPOST请求更新用户个人信息。

1.实现步骤

  1. 定义路由
  2. 验证表单数据
  3. 更新用户信息

2.定义路由和处理函数

  1. /router/my.js中新增POST路由
//更新信息router.post('/info', myHandler.setInfo)
  • 1
  • 2
  1. 添加处理函数
//router_handler/my.js//设置用户信息exports.setInfo = (req, res) => {    res.rend('post /my/info handler')}
  • 1
  • 2
  • 3
  • 4
  • 5
  1. 测试路由

3.参数验证

  1. 定义验证规则

新建/schema/my.js文件,编辑如下:

//schema/my.js//导入验证规则模块const joi = require('joi')//定义验证规则const id = joi.number().integer().min(1).max(10).required()const nickname = joi.string().required()const email = joi.string().email().required()//导出验证规则exports.update_info_schema = {    body: {        id,        nickname,        email    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  1. 引入验证中间件

/router/my.js中引入express-joi中间件

// 引入验证中间件const express_joi = require('@escook/express-joi')
  • 1
  • 2
  1. 引入验证规则

/router/my.js中引入joi验证规则

// 引入验证规则const { update_info_schema } = require('../schema/my')
  • 1
  • 2
  1. /my/infoPOST路由添加验证
//更新信息router.post('/info', express_joi(update_info_schema), myHandler.setInfo)
  • 1
  • 2
  1. 验证测试

如果我们不提供id参数,就会报如下错误。

如果我们提供正确的参数,将获得如下结果:


网站建设定制开发 软件系统开发定制 定制软件开发 软件开发定制 定制app开发 app开发定制 app开发定制公司 电商商城定制开发 定制小程序开发 定制开发小程序 客户管理系统开发定制 定制网站 定制开发 crm开发定制 开发公司 小程序开发定制 定制软件 收款定制开发 企业网站定制开发 定制化开发 android系统定制开发 定制小程序开发费用 定制设计 专注app软件定制开发 软件开发定制定制 知名网站建设定制 软件定制开发供应商 应用系统定制开发 软件系统定制开发 企业管理系统定制开发 系统定制开发