文章目录

  • 1.初始化项目
    • 1-1.创建项目
    • 1-2.配置cors
    • 1-3.配置解析表单数据的中间件
  • 2.初始化路由
    • 2-1.初始化路由相关的文件夹
    • 2-2.初始化用户路由模块
    • 2-3.抽离路由函数中的处理函数
  • 3.注册接口
    • 3-1.新建 ev_users 表
    • 3-2.安装并且配置mysql模块
    • 3-3.注册
      • 3-3-1.实现步骤
      • 3-3-2.检验表单数据是否合法
      • 3-3-3.检验用户名是否被占用
      • 3-3-4.对密码进行加密处理
      • 3-3-5.插入新用户
  • 4.代码优化
    • 4-1.优化res.send()代码
    • 4-2.验证规则
  • 5.登录接口
    • 5-1.实现步骤
    • 5-2.检测表单数据是否合法
    • 5-3.根据用户名查询用户的数据
    • 5-4.判断用户输入的密码是否正确
    • 5-5.生成JWT的token字符串
    • 5-6.配置解析token的中间件
  • 6.个人中心(开发获取用户的基本信息的接口)
    • 6-1.初始路由模块
    • 6-2.初始路由处理函数的模块
    • 6-3.获取用户的基本信息
  • 7.个人中心(更新用户信息的接口)
    • 7-1.定义路由和处理函数
    • 7-2.验证表单数据 (nickname和email)
    • 7-3.实现更新用户基本信息的功能
  • 8.个人中心(重置密码的接口)
    • 8-1.定义路由和处理函数
    • 8-2.验证表单数据
    • 8-3.实现重置密码功能

1.初始化项目

1-1.创建项目

  1. 新建api_server文件夹,运行
npm init -y
  1. 安装exoress
npm i express
  1. 在项目中新建app.js作为整个项目的入口文件,并创建服务器
// 导入模块
const express = require('express')// 创建服务器
const app = express()// 启动服务器
app.listen(80,(req,res)=>{console.log(run in localhost);
})

1-2.配置cors

  1. 安装cors中间件
npm i cors
  1. 在app.js中导入中间件
// 导入中间件
const cors = require('cors')
  1. 注册cors中间件
// 注册全局中间件
app.use(cors())

1-3.配置解析表单数据的中间件

  1. 配置解析application/x-www-form-urlencoided表单数据的中间件
  2. urlencoded()是express内置的方法
app.use(express.urlencoded({extended:false}))

2.初始化路由

2-1.初始化路由相关的文件夹

  1. 在项目根目录中,新建router文件夹,用来存放所有的路由模块

路由模块中,只存放客户端的请求与处理函数之间的映射关系

  1. 在项目根目录中,新建router_handler文件夹,用来存放所有的路由处理函数模块

路由处理函数模块中,专门负责存放每个路由对应的处理函数

2-2.初始化用户路由模块

  1. router文件夹中,新增use.js文件,作为用户的路由模块,初始化代码如下
const express = require('express')
const router = express.Router()// 注册新用户
router.post('/reguser',(req,res)=>{res.send('ok')
})// 登录
router.post('/losin',(req,res)=>{res.send('ok')})module.exports = router
  1. app.js中,导入并且使用用户路由模块
const userRouter = require('./router/user')
app.use('/api',userRouter)

2-3.抽离路由函数中的处理函数

目的 :为了保证路由模块的纯粹性,所有的路由处理函数,必须抽离到对应的路由处理函数模块中

  1. /router_handler/user.js 中,使用 exports 对象 , 分别向外共享两个 路由处理函数
// 定义一些路由处理函数供路由模块使用
// 注册用户的处理函数
exports.reguser = (req,res)=>{res.send('reguser ok')
}
// 登录的处理函数
exports.login = (req,res)=>{res.send('login ok')
}
  1. 将/router/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

3.注册接口

3-1.新建 ev_users 表

  1. 新建my_db_01 数据库中,新建 ev_users 表

3-2.安装并且配置mysql模块

  1. 运行如下命令,安装 mysql 模块
npm i mysql
  1. 在项目根目录中新建 /db/index.js 文件,在此自定义模块中创建数据库的连接对象
const mysql = require('mysql')// 创建数据库连接对象
const db = mysql.createPool({host:'127.0.0.1',user:'root',password:'qwer',database:'my_db_01'
})module.exports = db

3-3.注册

3-3-1.实现步骤

  1. 检验表单数据是否合法
  2. 检验用户名是否被占用
  3. 对密码进行加密处理
  4. 插入新用户

3-3-2.检验表单数据是否合法

  1. 判断用户名和密码是否为空
 // 获取客户端提交到服务器的用户信息const userinfo = req.body// 对表单中的数据进行判断if(!userinfo.username || !userinfo.password){return res.send({status:1,message:'用户可或者密码不能为空'})}

3-3-3.检验用户名是否被占用

  1. 导入数据库操作模块(在router_handler下面的user.js中)
// 导入数据库操作模块
const db = require('../db/index')
  1. 定义sql语句
// 注册用户的处理函数
exports.reguser = (req,res)=>{// 获取客户端提交到服务器的用户信息const userinfo = req.body// 对表单中的数据进行判断if(!userinfo.username || !userinfo.password){return res.send({status:1,message:'用户可或者密码不能为空'})}// 定义sql语句,查询用户名是否被占用const sqlStr = 'select * from ev_users where username=?'db.query(sqlStr,userinfo.username,(err,results)=>{// 执行语句失败if(err){return res.send({status:1,message:err.message})}// 判断用户是否被占用if(results.length > 0 ){return res.send({status:1,message:'用户名被占用'})}// 用户名可以使用,待会写})res.send('reguser ok')
}
  1. 执行sql语句并根据结果判断用户名是否被占用
 // 判断用户是否被占用if(results.length > 0 ){return res.send({status:1,message:'用户名被占用'})}// 用户名可以使用,待会写

3-3-4.对密码进行加密处理

为了保证密码的安全性,不建议在数据库以明文的形式保存用户密码,推荐对密码进行加密存储
在当前项目中,使用berypjs 对用户密码进行加密,优点:
1.加密之后的密码,无法被逆向破解
2.同一明文密码多次加密,得到的加密结果各不相同,保证了安全性

  1. 运行以下命令安装bcryptjs
npm i bcryptjs
  1. 在**/router handler/user.js中,导入bcrypt.js**
// 导入bcryptjs
const bcrypt = require('bcryptjs')
  1. 在注册用户的处理函数中,确认用户名可用之后,调用berypt .hashSync(明文密码,随机盐的长度)方法,对用户的密码进行加密处理:
在这里插入代码片

3-3-5.插入新用户

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

4.代码优化

4-1.优化res.send()代码

在处理函数中,需要多次调用res. send()向客户端响应处理失败的结果, 为了简化代码,可以手动封装一个res.cw()函数

  1. 在app.js 中,所有路由之前,声明一一个全局中间件,为res对象挂载-一个res.cc() 函数:
// 代码优化,在路由前面封装res.cw函数
app.use((req,res,next)=>{//status 的值默认为1 ,表示注册失败//err 的值可能是个错误对象也可能是个字符串res.cw = (err,status = 1)=>{res.send({status,message:err instanceof Error ? err.message : err})}next()
})

4-2.验证规则

  1. 在router_handler下面的router.js中添加下面规则代码
// 3.对表单数据进行验证看是否合法// 用户名由英文、数字组成const userTest = /^[0-9a-zA-Z]\w{1,11}$/// 密码由英文、数字组成const pwdTest = /^[0-9a-zA-Z]\w{2,11}$/// console.log(!userTest.test(userinfo.username));// console.log(!pwdTest.test(userinfo.password));if (!userTest.test(userinfo.username)) {return res.cw('用户名不合法')} else if(!pwdTest.test(userinfo.password)){return res.cw('密码不合法')}

5.登录接口

5-1.实现步骤

  1. 检测表单数据是否合法
  2. 根据用户查询用户的数据
  3. 判断用户输入的密码是否正确
  4. 生成JWT的token数据

5-2.检测表单数据是否合法

  1. 将/router/user.js中的登录路由修改如下
// 登录的处理函数
exports.login = (req, res) => {// 1.获取客户端提交到服务器的用户信息const userinfo1 = req.body
// 2.对表单数据进行验证看是否合法// 用户名由英文、数字组成const userTest = /^[0-9a-zA-Z]\w{1,11}$/// 密码由英文、数字组成const pwdTest = /^[0-9a-zA-Z]\w{1,11}$/if (!userTest.test(userinfo1.username)) {return res.cw('用户名不合法')} else if(!pwdTest.test(userinfo1.password)){return res.cw('密码不合法')}res.send('登陆成功')
}

5-3.根据用户名查询用户的数据

  1. 定义sql语句
// 3-1.定义sql语句const sql = 'select * from ev_users where username:?'
  1. 将/router/user.js中的登录路由修改如下
// 3.根据用户名查询用户的数据// 3-1.定义sql语句const sql = 'select * from ev_users where username:?'// 3-2.执行sql语句,查询用户数据db.query(sql,userinfo.username,(err,results)=>{// 3-3.执行sql语句失败if(err){res.cw(err)}// 3-4.执行sql语句成功,但是得到的数据不等于1if(results.length != 1){res.cw('登陆失败')}})res.send('登陆成功')

5-4.判断用户输入的密码是否正确

核心实现思路:调用berypt . compareSyne(用户提交的密码,数据库中的密码)方法比较密码是否一致
返回值是布尔值(true- 致,false 不一致)
具体实现代码如下:

// 4判断用户输入的密码是否正确//拿着用户输入的密码,和数据库中存储的密码进行对比const conpareResult = bcrypt.compareSync(userinfo.password,results[0],password)//如果对比的结果等于false, 则证明用户输入的密码错误if(!conpareResult){return res.cw('登陆失败')}res.send('登陆成功')
}

5-5.生成JWT的token字符串

为了不让token把生成的字符串中的密码头像中的值返回给客户端,在生成token的时候把他们剔除 了

  1. 通过es6语法,快速剔除密码和头像的值
// 5-1.剔除密码和头像、const user = {...results[0],password:'',user_pic:''}// console.log(user);
  1. 运行命令安装生成token字符串的包jsonwebtoken包
npm i jsonwebtoken
  1. 在**/router_handler/user.js模块的头部区域,导入jsonwebtoken包**
// 导入生成token的包
const jwt = require('jsonwebtoken')
// 导入全局配置文件
const config = require('../config')
  1. 根目录创建config.js文件,并向外共享加密和还原token的jwtSecretKey字符串
// 这是一个全局的配置文件
module.exports = {// 加密密钥jwtSecretKey:'liuq520 ^_^'
}
  1. 将用户信息对象加密成token字符串
// 5-2.对用户信息进行加密,生成token字符串const tokenStr = jwt.sign(user,config.jwtSecretKey,{expiresIn:'10h'})
  1. 将生成的token字符串响应给客户端
res.send({status:0,message:'登陆成功',token:'Bearer ' + tokenStr})

5-6.配置解析token的中间件

  1. 安装express-jwt中间件
npm i express-jwt@5.3.3
  1. 在app.js中注册路由之前,配置解析token的中间件
app.use(expressJWT({secret:config.jwtSecretKey}).unless({path:[/^\/api\]}))
  1. 在app.js中的错误级别中间件里面捕获并且处理token认证失败后的错误
// 定期错误级别的中间件
app.use((err,req,res,next)=>{//验证失败导致的错误if(err instanceof joi.ValidationError){return res.cw(err)}// 身份认证失败后的错误if(err.name === 'UnauthorizedError'){return res.cw('身份认证失败')}// 未知错误res.cw(err)
})

6.个人中心(开发获取用户的基本信息的接口)

6-1.初始路由模块

  1. 在router目录下创建userinfo.js路由模块,并且初始化如下代码
const express = require('express')
const router = express.Router()// 注册新用户
router.get('/userinfo',(req,res)=>{res.send('ok')
})module.exports = router
  1. 在app.js中导入并使用个人中心的路由模块
// 导入userinfo的路由模块
const userinfoRouter = require('./router/userinfo')
app.use('/my',userinfoRouter)

6-2.初始路由处理函数的模块

  1. 创建/router_handler/userinfo.js路由处理函数,并且初始化如下代码
exports.getUserInfo = (req,res)=>{res.send('ok')
}
  1. 修改/router/userinfo.js中的代码
const express = require('express')
const router = express.Router()
// 导入事件处理函数
const userinfo_handler = require('../router_handler/userinfo')// 注册新用户
router.get('/userinfo',userinfo_handler.getUserInfo)module.exports = router

6-3.获取用户的基本信息

  1. 导入数据库在处理函数userinfo.js中
const db = require('../db/index')
  1. 定义sql语句
// 定义sql语句,根据用户id,查询用户基本信息const sql = 'select id , username , nickname , email , user_pic from ev_users where id=?'
  1. 调用db.query()执行sql语句
db.query(sql,req.user.id,(err,results)=>{// 解析成功后的token的值会挂在到req上// 执行sql失败if(err){return res.send(err)}if(results.length !== 1){res.send('获取用户信息失败')}res.send({status:0,message:'获取用户信息成功',data:results[0]})})

7.个人中心(更新用户信息的接口)

7-1.定义路由和处理函数

  1. 在/router/userinfo.js 模块中,新增更新用户基本信息的路由:
    // 更新用户信息的接口
router.post('/userinfo',userinfo_handler.updateUserInfo)
  1. 在/router. handler/userinfo.js模块中,定义并向外共享更新用户基本信息的路由处理函数:
    // 1.更新用户信息exports.updateUserInfo = (req,res)=>{res.send('ok')}

7-2.验证表单数据 (nickname和email)

  1. 直接在处理函数中的userinfo.js 的updateInfo添加代码
// 1.更新用户信息exports.updateUserInfo = (req,res)=>{// 1.获取客户端提交到服务器的用户信息const userinfo = req.body// 验证表单数据 (nickname和email)// 昵称由英文、数字组成const nicknameTest = /^[0-9a-zA-Z]\w{1,11}$/// 邮箱由英文、数字组成const emailTest = /^[0-9a-zA-Z]\w{2,11}$/// console.log(!userTest.test(userinfo.username));// console.log(!pwdTest.test(userinfo.password));if (!nicknameTest.test(userinfo.nickname)) {return res.cw('昵称不合法')} else if(!emailTest.test(userinfo.email)){return res.cw('邮箱不合法')}res.send('ok')}

7-3.实现更新用户基本信息的功能

  1. 定义待执行的sql语句
    // 2-1.定义sql语句const sql = 'update ev_users set ? where id=?'
  1. 调用db.query()执行sql语句
// 2-2. 调用db.query()执行sql语句db.query(sql,[req.body,req.body.id],(err,results)=>{// 执行sql语句失败if(err){return res.send(err)}// z执行sql语句成功,但是行数不为1if(results.affectedRows != 1){return res.send('修改用户信息失败')}// 修改用户信息成功、return res.send('修改用户信息成功')})

8.个人中心(重置密码的接口)

8-1.定义路由和处理函数

  1. . 在/router/userinfo.js 模块中,新增重置密码的路由
// 3.重置密码的接口
router.post('/updatepwd',userinfo_handler.updatePassword)
  1. 在/router. .handler/userinfo.js模块中,定义并向外共享重置密码的路由处理函数:
    // 1.重置密码exports.updatePassword = (req,res)=>{res.send('ok')}

8-2.验证表单数据

// 1.重置密码exports.updatePassword = (req,res)=>{// 1.获取客户端提交到服务器的用户信息const userinfo = req.body// 验证表单数据 (nickname和email)// 新密码由英文、数字组成const newPwd = /^[0-9a-zA-Z]\w{1,11}$/if (!newPwd.test(userinfo.password)) {return res.send('新密码不合法')} return res.send('ok')}

8-3.实现重置密码功能

  1. 定义待执行的sql语句
    // 2-1.定义sql语句const sql = 'update ev_users set ? where id=?'
  1. 调用db.query()执行sql语句
//2.实现更新用户密码功能const sql = 'update ev_users set ? where id=?'// 2-2. 调用db.query()执行sql语句db.query(sql,[req.body,req.body.id],(err,results)=>{// 执行sql语句失败if(err){return res.send(err)}// z执行sql语句成功,但是行数不为1if(results.affectedRows != 1){return res.send('修改密码失败')}// 修改用户信息成功、return res.send('修改用户信息成功')})

Node开发后台API接口项目相关推荐

  1. 【node.js后台api项目】(七)更新用户头像接口

    [node.js后台api项目](七)更新用户头像接口 1.接口相关信息 2. 定义路由和处理函数 3.验证提交的数据 4.实现更新用户基本信息功能 1.接口相关信息 路由: /my/update/a ...

  2. 【node.js后台api项目】(二)实现注册功能

    [node.js后台api项目](二)实现注册功能 一.实现思路 二.项目目录 三.代码编写 1.基本代码 2.数据合法性校验 3.注册路由处理函数 4.密码加密 一.实现思路 注册功能简单来说就是提 ...

  3. 后台接收数组_微信小程序如何与后台api接口进行数据交互(微信报修小程序源码讲解七)...

    完成用户授权登录逻辑后,接下来的开发工作大部分都是与后台 api 接口的交互,本节我们详细讲解一下小程序如何与 api 进行交互 . 小程序如何发送 http/https 请求到后台? 小程序请求 h ...

  4. axios vue 回调函数_VUE使用axios调用后台API接口的方法

    VUE使用axios调用后台API接口的方法 引言 Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式JavaScript框架.与其它大型框架不同的是,Vue 被设计为可 ...

  5. 小程序与后台 api接口数据交互详解(微信报修小程序源码讲解七)

    完成用户授权登录逻辑后,接下来的开发工作大部分都是与后台 api 接口的交互,本节我们详细讲解一下小程序如何与 api 进行交互 . 小程序如何发送 http/https 请求到后台? 小程序请求 h ...

  6. 基于Alios的后台API接口任务

    基于Alios的后台API接口任务 月初论文已经提交外审了,前两天接到一个任务是将之前开发的基于Alios的门禁系统接入到公司的新服务器中,后台程序由我来写,这对于我来说还是一个新的挑战. 周一 周一 ...

  7. Vue电商系统后台API接口

    项目演示入口 ===> 1. 电商管理后台 API 接口文档 1.1. API V1 接口说明 接口基准地址:http://127.0.0.1:8888/api/private/v1/ 服务端已 ...

  8. 使用Express开发小说API接口服务1.0(二)

    使用Express开发小说API接口服务1.0(二) 线上访问地址api.langpz.com/ 之前完成了首页和搜索的接口,现在就开始写剩下的接口. 获取小说源 因为追书神器正版源是收费加密的,所以 ...

  9. 百度AI人工智能开发平台api接口强---使用有感

    2019年上半年由于期末要求,无意中想到想做一个识别植物得小程序,但由于时间以及自己没有接触识别算法这方面知识,所以调用接口,后再搜索过程中,了解到了百度AI人工智能开发平台api接口(https:/ ...

最新文章

  1. Python设计模式-解释器模式
  2. C++_泛型编程与标准库(九)——红黑树的使用
  3. 机器人“快递小哥”上岗了!京东配送机器人编队长沙亮相
  4. Linux学习8之Shell编程--基础正则表达式
  5. ssl1203-书的复制【dp】
  6. 程序员的算法课(17)-常用的图算法:深度优先(DFS)
  7. Android 4.0 ICS SystemUI浅析——SystemUI启动流程
  8. Android系统启动流程源码分析
  9. TensorFlow 学习------第一天
  10. 对于有Id,ParentId,Name这样类型字段的表的一个sql查询
  11. javascript(JS)混淆工具
  12. 西门子PLC丨虚拟机运行仿真器供物理主机使用
  13. ST_Intersects
  14. linux下故障硬盘点灯操作
  15. 电商数据分析--常见的数据采集工具及方法
  16. 上云就上百度智能云,百度智能计算峰会召开,AI原生云全新升级
  17. 使用MySQL,请用好 JSON 这张牌!
  18. 无法停止USB设备通用卷的解决办法
  19. 3自由度并联绘图机器人实现写字功能(二)
  20. Java修炼之凡界篇 筑基期 第02卷 语法 第03话 数据类型

热门文章

  1. 小鹤双拼提速方法个人经验-by老随风
  2. Matlab用三种格式来表示日期与时间
  3. 简述思科、华为交换机型号字母代表的意思
  4. 沙特阿美以246亿元收购荣盛石化10%股份,还将在中国东北建设大型炼化一体化项目...
  5. mapActions
  6. 锁升级过程(偏向锁/轻量级锁/重量级锁)
  7. 微信小程序音频的使用:wx.createInnerAudioContext的使用
  8. ubuntu server 安全模式磁盘检查修复
  9. 最新的三星android版本号,三星率先公布Android 12/13升级机型名单,可惜S9/Note9被抛弃...
  10. 来听听外国UX设计师的22句话