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

  • 一、实现思路
  • 二、项目目录
  • 三、代码编写
    • 1、基本代码
    • 2、数据合法性校验
    • 3、注册路由处理函数
    • 4、密码加密

一、实现思路

注册功能简单来说就是提供一个路由,命中路由后把用户名和密码插入数据库。但是也有一些细节需要注意

  • 对前端传过来的值需要先进行合法性校验。
  • 规定用户名必须唯一,因此在往数据库插入用户信息前需要先检查用户名是否存在,若存在则响应客户端告知更改用户名。
  • 考虑到密码的安全性,我们不直接将密码明文保存在数据库,而是加密以后再存入数据库,可以利用一些第三方的npm包来实现这个需求。
  • 我们可以直接在appappapp上挂在路由,但是考虑到我们将来要书写众多的路由,我们可以把路由抽离出来,使用express.Router()得到router对象,在routerrouterrouter对象上挂在路由,然后再通过app.use()使用该路由对象,从而实现模块化开发。

二、项目目录

项目目录结构如下
---- api_server
    ---- router
        ---- user.js
    ---- router_handler
      ---- user.js
    ----app.js
    ---- schema
        ---- user.js
router里存放路由关系,router_handler里存放路由处理函数。
schema用于放置数据校验规则的配置文件。

三、代码编写

1、基本代码

    ---- router
        ---- user.js

const express = require('express')
// 导入路由处理函数
const userHandler = require('../router_handler/user.js')
//调用express.Router()方法,该方法返回一个对象
const router = express.Router()// 注册路由
router.post('/register', userHandler.register)module.exports = router

    ---- app.js

// 导入user路由
const userRouter = require('./router/user.js')
// 使用路由,当第一个参数传入一个路由前缀时,会给所有userRouter上的路由路径加上该前缀,即我们访问的是 /api/login、/api/register
app.use('/api', userRouter)

    ---- router_handler
        ---- user.js

const register = (req , res) => {res.send('命中注册路由!')
}module.exports = {login
}

到了这一步,我们可以先使用postman等apiapiapi测试工具,访问 http://127.0.0.1/api/login,如果成功返回 命中注册路由 , 说明接口已经跑通,可以进行接下来的编写了。

2、数据合法性校验

这一步我们通过 req.body(express.urlencoded解析数据后挂在在req.body上的)可以拿到前端传过来的数据,最简单的就是使用 if...else...判断使得用户名和密码符合我们的要求。

const register = (req, res) => {const userInfo = req.bodyif(!userInfo.username || !userInfo.password) return res.send({status: 1 , message: '注册失败!'})//其他的条件...
}

上面只是一个示例,验证了用户名或密码为空的情况,但是还有很多其他的校验还没做,如果都用 if...else...进行判断,代码冗余,可读性变差,因此我们可以借助一些第三方的包来做这个功能。
这里使用joi这个包来实现数据校验功能。

// ./schema/user.js
// 导入joi包用于数据校验
const Joi = require('joi')// 定义登录注册的校验规则
const reg_login_schema = {//string()字符串,alphaum()数字和字母的组合,//min(1)长度最小为1,max(10)最大为10,required()这个值是必须有的username: Joi.string().alphanum().min(1).max(10).required(),password: Joi.string().pattern(/^[\S]{6,12}$/).required()
}

上面的代码导入了joijoijoi这个包,然后定义了一个对象,该对象里分别对用户名和密码做出一些约束。
由于登录和注册都需要对用户名密码进行合法性校验,所有我们可以封装一个自定义的中间件。

// ./schema/user.js
// 定义登录注册数据校验中间件
const joiExpress = (req, res, next) => {//根据文档使用Joi即可const schema = Joi.object(reg_login_schema)const userInfo = req.body ? req.body : {}//当匹配成功时,err的值是undefinedconst { error } = schema.validate(userInfo)if (error) res.cc(error)//自定义中间件一定记得调用next()方法,否则服务可能会在这里停止next()
}// 导出该中间件
module.exports = joiExpress
// ./router/user.js
// 导入自定义的登录注册数据校验中间件
const joiExpress = require('../schema/user')// 在该路由下使用中间件
router.post('/register', joiExpress, userHandler.register)

3、注册路由处理函数

基本代码如下

// ./router_handler/user.js
// 注册路由处理函数
const register = (req, res) => {const userInfo = req.body// 检查用户名是否已存在let sql = `select * from ${usersTable} where username=?`db.query(sql, [userInfo.username], (err, result) => {if (err) return res.send({status: 1 , message: err.message})if (result.length > 0) return res.send({status: 1 , message: '用户名已存在,请更换用户名!'})// 执行注册操作let insertSql = `insert into ${usersTable} set ?`// 将用户信息存入数据库db.query(insertSql, { username: userInfo.username, password: userInfo.password }, (err, result) => {if (err) return res.cc(err)if (result.affectedRows >= 1) res.send({status: 1 , message: '用户名已存在,请更换用户名!'})else res.send({status: 1 , message: '注册失败!请稍后重试~'})})})
}

上面的代码我们重复书写了很多次res.send(),且返回的数据对象有统一的格式,因此我们可以再进行一层封装,编写一个自定义中间件。

// ./app.js// 自定义处理错误中间件
app.use((req, res, next) => {//在res对象上挂载cc函数,之后的req上都会拥有该cc函数res.cc = (err, status = 1) => {err = err instanceof Error ? err.message : errres.send({status,message: err})}next()
})// 使用路由,上面的中间件必须在下面这一行挂在路由的前面引入
app.use('/api', userRouter)

有了这个中间件,将代码更改一下

// ./router_handler/user.jsconst register = (req, res) => {const userInfo = req.body// 检查用户名是否已存在let sql = `select * from ${usersTable} where username=?`db.query(sql, [userInfo.username], (err, result) => {if (err) return res.cc(err)if (result.length > 0) return res.cc('用户名已存在,请更换用户名!')// 执行注册操作let insertSql = `insert into ${usersTable} set ?`// 将用户信息存入数据库db.query(insertSql, { username: userInfo.username, password: userInfo.password }, (err, result) => {if (err) return res.cc(err)if (result.affectedRows >= 1) res.cc('注册成功!', 1)else res.cc('注册失败,请稍后重试~')})})
}

4、密码加密

// ./router_handler/user.js// 导入bcryptjs用于密码加密
const bcrypt = require('bcryptjs')// 注册路由处理函数
const register = (req, res) => {const userInfo = req.body// 检查用户名是否已存在let sql = `select * from ${usersTable} where username=?`db.query(sql, [userInfo.username], (err, result) => {if (err) return res.cc(err)if (result.length > 0) return res.cc('用户名已存在,请更换用户名!')// 执行注册操作let insertSql = `insert into ${usersTable} set ?`// 将明文密码进行加密userInfo.password = bcrypt.hashSync(userInfo.password, 10)// 将用户信息存入数据库db.query(insertSql, { username: userInfo.username, password: userInfo.password }, (err, result) => {if (err) return res.cc(err)if (result.affectedRows >= 1) res.cc('注册成功!', 1)else res.cc('注册失败,请稍后重试~')})})
}

【node.js后台api项目】(二)实现注册功能相关推荐

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

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

  2. Vue项目二 登录注册功能的实现

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.系统注册功能的实现 1.配置注册页面路由 2.注册页面的搭建 3.api下发送ajax请求的文件创建 二.后台数据 ...

  3. Node.js详解(二):Node.js与JS的关系

    一.简介 Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境,是一个让 JavaScript 运行在服务端的开发平台,它让 JavaScript 成为与PHP.Py ...

  4. Vanilla Node.js REST API示例

    A Vanilla Node.js REST API without Frameworks such us Express | Engineering Education (EngEd) Progra ...

  5. Node.js核心入门(二)

    目录: Node.js核心入门(一) 全局对象 常用工具 事件机制 Node.js核心入门(二) 文件系统访问 HTTP服务器与客户端 文件系统 fs fs 模块是文件操作的封装,它提供了文件的读取. ...

  6. api怎么写_使用Node.js原生API写一个web服务器

    Node.js是JavaScript基础上发展起来的语言,所以前端开发者应该天生就会一点.一般我们会用它来做CLI工具或者Web服务器,做Web服务器也有很多成熟的框架,比如Express和Koa.但 ...

  7. Node.js Express+Mongodb 项目实战

    Node.js Express+Mongodb 项目实战 这是一个简单的商品管理系统的小项目,包含的功能还算挺全的,项目涵盖了登录.注册,图片上传以及对商品进行增.删.查.改等操作,对于新手来说是个很 ...

  8. node.js 学习笔记(二)模板引擎和C/S渲染

    node.js 学习笔记(二)模板引擎和C/S渲染 文章目录 node.js 学习笔记(二)模板引擎和C/S渲染 一.初步实现Apache功能 1.1 使用模板引擎 1.2 在 node 中使用模板引 ...

  9. 十个书写Node.js REST API的最佳实践(上)

    收录待用,修改转载已取得腾讯云授权 原文:10 Best Practices for Writing Node.js REST APIs 我们会通过本文介绍下书写Node.js REST API的最佳 ...

最新文章

  1. Android No static field XXX of type I in class Lcom/XXX/R$id错
  2. 几何梯度分析神经网络中不可信预测性
  3. Python基础概念_10_异常处理
  4. Github标星3w+,热榜第一,如何用Python实现所有算法
  5. 创业-程序员独自5大思维障碍
  6. 第五十九期:如何在Windows 10中执行Windows Defender离线扫描?
  7. centOS7安装matlab2014a
  8. PowerDesigner 中的name与comment转换(转)
  9. 【学时总结】 ◆学时·IV◆ 数位DP
  10. 程序员的自我修养 - 符号修饰 函数签名 以及一个引申的问题: extern c
  11. mysql资源限制_超出了MariaDB / MySQL资源限制
  12. 输出字符串全排列 c语言,41.输出全排列-题解(C语言代码)
  13. c# 使用winform内嵌浏览器
  14. 5s管理常用工具汇总
  15. 越狱相关三:OpenSSH
  16. 左连接 oracle条件查询,sql 左连接查询条件and与where
  17. 一款网页游戏外挂开发-数据抓包2
  18. Windows操作系统名称与版本号汇总
  19. Timeout waiting for connection from pool
  20. 深度学习(16):print(torch.cuda.is_available()) False的一个解决流程/思路

热门文章

  1. 有效解决VS 无法启动 IIS EXPRESS Web 服务器。(ID为xxxxx的进程当前未运行)
  2. 江苏大学考研805真题C语言程序设计 第五大编程题答案2004-2019
  3. SCI写作分析篇(一)
  4. 2022年嵌入式秋招题目及解答
  5. K_A08_005 基于 STM32等单片机驱动XY-160D模块按键控制直流电机正反转加减速启停
  6. 计算机音乐乐谱小幸运,田馥甄小幸运尤克里里四线谱
  7. Redis之数据类型详解分析
  8. php用户注册功能设计,利用HTML+CSS设计一个简单的用户注册页面【示例】
  9. 分布式发布订阅消息系统—Apache Kafka
  10. 『Android安全』版优秀和精华帖分类索引