ToB企服应用市场:ToB评测及商务社交产业平台

标题: (内附源码)Node.js小试——使用Node开发API服务器、登录、注册、加密、表 [打印本页]

作者: 渣渣兔    时间: 2022-6-24 07:56
标题: (内附源码)Node.js小试——使用Node开发API服务器、登录、注册、加密、表


文章目录



源码链接(免积分、不付费)
初始化Node.js项目

1.创建项目

  1. mkdir ExpressServer && cd ExpressServer
  2. npm init -y
复制代码
  1. npm i express
复制代码
  1. //1. 导入express模块
  2. const express = require('express')
  3. //2. 创建express服务器实例
  4. const server = express()
  5. // TODO:在这里编写服务器代码
  6. //3. 监听服务器80端口
  7. server.listen(80, () => {
  8.     console.log('Express server running on http://127.0.0.1:80')
  9. })
复制代码
2.配置cors跨域

  1. npm i cors
复制代码
  1. //1. 导入cors中间件
  2. const cors = require('cors')
  3. //2. 注册cors中间件
  4. server.use(cors())
复制代码
3.配置表单数据解析中间件

  1. server.use(express.urlencoded({ extended: false }))
复制代码
4.初始化路由文件夹

  1. mkdir router
  2. mkdir router_handler
复制代码
5.初始化路由模块

  1. const express = require('express')
  2. //创建路由对象
  3. const router = express.Router()
  4. //用户注册路由
  5. router.post('/register', (req, res) => {
  6.     res.send('POST /register')
  7. })
  8. //用户登录路由
  9. router.post('/login', (req, res) => {
  10.     res.send('POST /login')
  11. })
  12. //共享router对象
  13. module.exports = router
复制代码
  1. //导入用户路由
  2. const authRouter = require('./router/auth')
  3. //注册用户路由
  4. server.use('/api/auth',authRouter)
复制代码
6.启动并测试服务器

  1. npm i -g nodemon
复制代码
  1. nodemon app.js
复制代码
如果操作正确,服务器正常启动,将输出如下内容:
  1. PS E:\ExpressServer> nodemon .\app.js
  2. [nodemon] 2.0.16
  3. [nodemon] to restart at any time, enter `rs`
  4. [nodemon] watching path(s): *.*
  5. [nodemon] watching extensions: js,mjs,json
  6. [nodemon] starting `node .\app.js`
  7. Express server running on http://127.0.0.1:80
复制代码


7.抽离路由处理函数

   为了保证路由模块的存粹性,将路由处理函数单独抽离出来放在router_handler文件夹中
  
  1. //router_handler/auth.js
  2. //注册处理函数
  3. exports.authRegister = (req, res) => {
  4.     res.send('POST /register')
  5. }
  6. //登录处理函数
  7. exports.authLogin = (req, res) => {
  8.     res.send('POST /login')
  9. }
复制代码
  1. //router/auth.js
  2. const express = require('express')
  3. //创建路由对象
  4. const router = express.Router()
  5. //引入auth处理模块
  6. const authHandler = require('../router_handler/auth')
  7. //用户注册路由
  8. router.post('/register', authHandler.authRegister)
  9. //用户登录路由
  10. router.post('/login', authHandler.authLogin)
  11. //共享router对象
  12. module.exports = router
复制代码
注册

1.创建数据库

  1. CREATE SCHEMA `db_node` ;
复制代码
  如果还没有安装MySql,可以在这里下载MySql安装器
  
  1. CREATE TABLE `db_node`.`t_users` (
  2.   `id` INT NOT NULL AUTO_INCREMENT,
  3.   `username` VARCHAR(255) NOT NULL,
  4.   `password` VARCHAR(255) NOT NULL,
  5.   `nickname` VARCHAR(255) NULL,
  6.   `email` VARCHAR(255) NULL,
  7.   `avatar` TEXT NULL,
  8.   PRIMARY KEY (`id`),
  9.   UNIQUE INDEX `id_UNIQUE` (`id` ASC) VISIBLE,
  10.   UNIQUE INDEX `username_UNIQUE` (`username` ASC) VISIBLE)
  11. ENGINE = InnoDB
  12. DEFAULT CHARACTER SET = utf8mb4
  13. COLLATE = utf8mb4_0900_ai_ci;
复制代码
2.安装并配置mysql模块

  1. npm i mysql
复制代码
  1. // db/index.js
  2. //导入mysql模块
  3. const mysql = require('mysql')
  4. //创建数据库连接对象
  5. const db = mysql.createPool({
  6.     host: '127.0.0.1',  //数据库服务器地址,我们使用本机
  7.     user: 'root',       //mysql用户名,替换为你的用户名
  8.     password: '000000', //mysql密码,替换为你的密码
  9.     database: 'db_node',//数据库名称,此处为db_node
  10. })
  11. //导出数据库连接对象
  12. module.exports = db
复制代码
3.注册


  1. const userinfo = req.body
  2.     if(!userinfo.username || !userinfo.password){
  3.         return res.send({
  4.             status: 201,
  5.             message:'用户名、密码不能为空!'
  6.         })
  7.     }
复制代码

  1. const db = require('../db/index')
复制代码

  1. sqlStr = 'select * from t_users where username = ?'
复制代码

  1. db.query(sql, userinfo.username, (err, results) => {
  2.         if (err) return res.send({ status: 201, message: err.message })
  3.         if(results.length > 0){
  4.             return res.send({status:201,message:'用户名已存在'})
  5.         }
  6.         //TODO:插入新用户
  7.     })
复制代码

  1. npm i bcryptjs
复制代码

  1. const bcrypt = require('bcryptjs')
复制代码

  1. userinfo.password = bcrypt.hashSync(userinfo.password,10)
复制代码

  1. sqlStr = 'insert into t_users set ?'
复制代码

  1. db.query(sql, { username: userinfo.username, password: userinfo.password }, (err, results) => {
  2.             if (err) return res.send({ status: 201, message: err.message })
  3.             if (results.affectedRows === 1)
  4.                 return res.send({ status: 200, message: 'success' })
  5.             return res.send({ status: 201, message: '注册失败,稍后再试' })
  6.         })
复制代码
4.注册测试



如此,注册方法变成功执行了。
优化res.send()

   我们在代码中多次使用到了res.send()方法,非常繁琐,需要封装简化代码。(不优化也没啥)
  
  1. server.use((req, res, next) => {
  2.     //status = 200 success
  3.     //status = 201 failure
  4.     res.cc = function (err, status = 1) {
  5.         res.send({
  6.             status: status,
  7.             message: err instanceof Error ? err.message : err,
  8.         })
  9.     }
  10.     next()
  11. })
复制代码
这样在所有的路由中,res都具有一个cc方法,可以方便的向客户端输出结果。
优化表单验证

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

1.安装joi包,为表单项定义验证规则
  1. npm i joi
复制代码
  1. npm i @escook/express-joi
复制代码
2.验证规则

  1. mkdir schema
  2. touch schema/auth.js
复制代码
  1. //schema/auth.js
  2. //导入包
  3. const joi = require('joi')
  4. /**
  5. * string() 字符串
  6. * alphanum() 字符数字串
  7. * min(len) 最短
  8. * max(len) 最长
  9. * required() 不为空
  10. * pattern(reg) 符合正则
  11. */
  12. //用户名密码验证规则
  13. const username = joi.string().alphanum().min(1).max(10).required()
  14. const password = joi.string().pattern(/^[\S]{6,12}$/).required()
  15. //登录注册验证对象
  16. exports.reg_login_schema = {
  17.     body: {
  18.         username,
  19.         password
  20.     }
  21. }
复制代码
4.插入验证中间件

  1. //引入验证中间件
  2. const expressJoi = require('@escook/express-joi') //(*)
复制代码
  1. //引入验证规则
  2. const { reg_login_schema } = require('../schema/auth')//(*)
复制代码
  1. //用户注册路由,添加验证中间件
  2. router.post('/register', expressJoi(reg_login_schema), authHandler.authRegister) //(*)
复制代码
修改后的route/auth.js,如下:
  1. //router/auth.jsconst express = require('express')//创建路由对象const router = express.Router()//引入验证中间件
  2. const expressJoi = require('@escook/express-joi') //(*)//引入验证规则
  3. const { reg_login_schema } = require('../schema/auth')//(*)//引入auth处理模块const authHandler = require('../router_handler/auth')//用户注册路由,添加验证中间件
  4. router.post('/register', expressJoi(reg_login_schema), authHandler.authRegister) //(*)//用户登录路由router.post('/login', authHandler.authLogin)//共享router对象module.exports = router
复制代码
注意以上代码中(*)处是修改的地方。
5.捕获验证错误

在app.js中创建并注册全局错误处理中间件,用于处理验证错误(也可以处理其他错误)。
  1. //引入验证规则模块
  2. const joi = require('joi')
复制代码
  1. //引入验证规则模块
  2. const joi = require('joi')//注册异常捕获中间件server.use((err, req, res, next) => {    if (err instanceof joi.ValidationError) return res.cc(err)    res.cc(err)})
复制代码
6.验证测试


登录

1.登录步骤

2.表单验证

  1. //用户登录路由
  2. router.post('/login', expressJoi(reg_login_schema), authHandler.authLogin)
复制代码
3.数据查询

在router_handler/auth.js中的登录处理方法中:
  1. const userinfo = req.body
复制代码
  1. const sqlStr = 'select * from t_users where username=?'
复制代码
  1. //执行查询
  2. db.query(sqlStr, userinfo.username, (err, results) => {
  3.     //查询失败
  4.     if (err) return res.cc(err)
  5.     //查询结果不合理
  6.     if (results.length !== 1) return res.cc("登录失败")
  7.     //TODO:判断密码
  8. })
复制代码
4.密码比较

   调用bcrypt.compreSync(表单密码,数据库密码)判断密码是否一致,true一致,false不一致
  1. //判断密码
  2. const cmpRes = bcrypt.compare(userinfo.password, results[0].password)
  3. if (!cmpRes) return res.cc('Login Failed')
  4. //TODO:登录成功,生成token
复制代码
5.生成token

  1. const usr = { ...results[0], password: '', avatar: '' }
复制代码
  1. npm i jsonwebtoken
复制代码
  1. const jwt = require('jsonwebtoken')
复制代码
  1. //config.js
  2. module.exports = {
  3.     //一个复杂字符串
  4.     jwtSecretKey: "alkjflasngaoieakgbnasdfzxfgasdf",
  5.     expiresIn: '24h',//token有效期24h
  6. }
复制代码
  1. //导入config
  2. const config = require('../config')
  3. //生成token
  4. const tokenStr = jwt.sign(usr, config.jwtSecretKey, {
  5.             expiresIn: config.expiresIn,//token有效期为24小时
  6. })
复制代码
  1. res.send({
  2.     status: 200,
  3.     message: 'login success',
  4.     token: 'Bearer ' + tokenStr
  5. })
复制代码

6.Token解析

  1. npm i express-jwt@5.3.3
复制代码
  1. const config = require('./config')
  2. //导入token中间件
  3. const expressJWT = require('express-jwt')
  4. //注册token中间件,所有以/api开头的路由都需要验证token的正确性
  5. server.use(expressJWT({ secret: config.jwtSecretKey }).unless({ path: [/^\/api\//] }))
复制代码
  1. if (err.name === 'UnauthorizedError') return res.cc('认证失败')
复制代码
访问非/api开头的路由即可,这里使用/my

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

获取用户信息

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

2.初始化/router/my.js

  1. // 引入express模块
  2. const express = require('express')
  3. //创建路由对象
  4. const router = express.Router()
  5. //挂接/info路由
  6. router.get('/info', (req, res) => {
  7.     res.send('ok')
  8. })
  9. //向外分享路由对象
  10. module.exports = router
复制代码
  1. //导入路由
  2. const myRouter = require('./router/my')
  3. //注册/my路由
  4. server.use('/my', myRouter)
复制代码
3.测试路由配置


复制返回的token字符串。

如果你和我的编码相同,返回ok即为正确。
4.初始化/router_handler/my.js

  1. //暴露/my/info路由的处理函数
  2. exports.getInfo = (req, res) => {
  3.     res.send('/my/info handler')
  4. }
复制代码
  1. // 引入express模块
  2. const express = require('express')
  3. //创建路由对象
  4. const router = express.Router()
  5. const myHandler = require('../router_handler/my') //(*)
  6. //挂接/info路由
  7. router.get('/info', myHandler.getInfo)//(*)
  8. //向外分享路由对象
  9. module.exports = router
复制代码
注意上述代码中(*)处的改动。

如果返回的内容和我一样就没有问题了。
5.获取用户信息

  1. const db = require('../db/index')
复制代码
  1. const sql = 'select id,username,nickname,email,avatar from t_users where id=?'
复制代码
  1. db.query(sql, req.user.id, (err, results) => {
  2.     if (err) return res.cc(err.message)
  3.     if (results.length !== 1) return res.cc('获取用户信息失败')
  4.     res.send({
  5.         status: 200,
  6.         message: 'Success',
  7.         data: results[0]
  8.     })
  9. });
复制代码
6.测试


这样就执行成功了。
更新用户信息

使用/my/info的POST请求更新用户个人信息。
1.实现步骤

2.定义路由和处理函数

  1. //更新信息
  2. router.post('/info', myHandler.setInfo)
复制代码
  1. //router_handler/my.js
  2. //设置用户信息
  3. exports.setInfo = (req, res) => {
  4.     res.rend('post /my/info handler')
  5. }
复制代码

3.参数验证

新建/schema/my.js文件,编辑如下:
  1. //schema/my.js
  2. //导入验证规则模块
  3. const joi = require('joi')
  4. //定义验证规则
  5. const id = joi.number().integer().min(1).max(10).required()
  6. const nickname = joi.string().required()
  7. const email = joi.string().email().required()
  8. //导出验证规则
  9. exports.update_info_schema = {
  10.     body: {
  11.         id,
  12.         nickname,
  13.         email
  14.     }
  15. }
复制代码
在/router/my.js中引入express-joi中间件
  1. // 引入验证中间件
  2. const express_joi = require('@escook/express-joi')
复制代码
在/router/my.js中引入joi验证规则
  1. // 引入验证规则
  2. const { update_info_schema } = require('../schema/my')
复制代码
  1. //更新信息
  2. router.post('/info', express_joi(update_info_schema), myHandler.setInfo)
复制代码

如果我们不提供id参数,就会报如下错误。
如果我们提供正确的参数,将获得如下结果:


源码链接(免积分、不付费)

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4