ToB企服应用市场:ToB评测及商务社交产业平台
标题:
(内附源码)Node.js小试——使用Node开发API服务器、登录、注册、加密、表
[打印本页]
作者:
渣渣兔
时间:
2022-6-24 07:56
标题:
(内附源码)Node.js小试——使用Node开发API服务器、登录、注册、加密、表
文章目录
初始化Node.js项目
1.创建项目
2.配置cors跨域
3.配置表单数据解析中间件
4.初始化路由文件夹
5.初始化路由模块
6.启动并测试服务器
7.抽离路由处理函数
注册
1.创建数据库
2.安装并配置mysql模块
3.注册
4.注册测试
优化res.send()
优化表单验证
1.安装包
2.验证规则
4.插入验证中间件
5.捕获验证错误
6.验证测试
登录
1.登录步骤
2.表单验证
3.数据查询
4.密码比较
5.生成token
6.Token解析
获取用户信息
1.基本步骤
2.初始化/router/my.js
3.测试路由配置
4.初始化/router_handler/my.js
5.获取用户信息
6.测试
更新用户信息
1.实现步骤
2.定义路由和处理函数
3.参数验证
源码链接(免积分、不付费)
初始化Node.js项目
1.创建项目
创建项目文件夹,并再项目根目录初始化npm包管理文件,以ExpressServer为例,代码如下:
mkdir ExpressServer && cd ExpressServer
npm init -y
复制代码
运行如下命令安装express:
npm i express
复制代码
创建项目入口文件,并初始化内容如下:
//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')
})
复制代码
2.配置cors跨域
运行如下命令安装cors中间件:
npm i cors
复制代码
在app.js中导入并配置cors中间件:
//1. 导入cors中间件
const cors = require('cors')
//2. 注册cors中间件
server.use(cors())
复制代码
3.配置表单数据解析中间件
配置如下代码,解析application/x-www-form-urlencoded格式的表单数据:
server.use(express.urlencoded({ extended: false }))
复制代码
4.初始化路由文件夹
项目根目录中,创建router文件夹,用于存放所有的路由模块
项目根目录中,创建router_handler文件夹,用于存放所有的路由处理模块
mkdir router
mkdir router_handler
复制代码
5.初始化路由模块
在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
复制代码
在app.js中,导入并注册用户路由模块:
//导入用户路由
const authRouter = require('./router/auth')
//注册用户路由
server.use('/api/auth',authRouter)
复制代码
6.启动并测试服务器
安装nodemon模块,用于启动服务器(nodemon模块可以在我们修改代码后自动重启服务器):
npm i -g nodemon
复制代码
使用nodemon模块启动服务器:
nodemon app.js
复制代码
如果操作正确,服务器正常启动,将输出如下内容:
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
复制代码
使用postman测试接口是否配置正确,以POST方式分别访问localhost/api/auth/register和localhost/api/auth/login
7.抽离路由处理函数
为了保证路由模块的存粹性,将路由处理函数单独抽离出来放在router_handler文件夹中
在router_handler文件夹中创建并编辑auth.js文件如下:
//router_handler/auth.js
//注册处理函数
exports.authRegister = (req, res) => {
res.send('POST /register')
}
//登录处理函数
exports.authLogin = (req, res) => {
res.send('POST /login')
}
复制代码
修改/router/auth.js文件代码如下:
//router/auth.js
const 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
复制代码
使用nodemon启动并使用postman访问localhost/api/auth/register和localhost/api/auth/login,会得到和之前(6.3)相同的结果。
注册
1.创建数据库
创建MySql数据库,此处以db_node为例:
CREATE SCHEMA `db_node` ;
复制代码
如果还没有安装MySql,可以在这里下载
MySql安装器
创建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 = InnoDB
DEFAULT CHARACTER SET = utf8mb4
COLLATE = utf8mb4_0900_ai_ci;
复制代码
2.安装并配置mysql模块
执行如下指令,安装mysql模块:
npm i mysql
复制代码
创建/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
复制代码
3.注册
注册步骤
检测表单数据
检测用户名是否占用
密码加密处理
插入新用户
检测表单数据
const userinfo = req.body
if(!userinfo.username || !userinfo.password){
return res.send({
status: 201,
message:'用户名、密码不能为空!'
})
}
复制代码
检测用户名是否占用
从db/index.js导入db
const db = require('../db/index')
复制代码
定义SQL
sqlStr = 'select * from t_users where username = ?'
复制代码
执行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:插入新用户
})
复制代码
密码加密
执行以下指令,安装bcryptjs模块
npm i bcryptjs
复制代码
在router_handler/auth.js中,导入bcryptjs
const bcrypt = require('bcryptjs')
复制代码
插入用户之前,使用bcrypt.hashSync(password,len)进行加密
userinfo.password = bcrypt.hashSync(userinfo.password,10)
复制代码
插入用户
定义SQL
sqlStr = 'insert into t_users set ?'
复制代码
执行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: '注册失败,稍后再试' })
})
复制代码
4.注册测试
使用PostMan发送注册信息,操作如下:
我们可以查看数据库:
如此,注册方法变成功执行了。
优化res.send()
我们在代码中多次使用到了res.send()方法,非常繁琐,需要封装简化代码。(不优化也没啥)
在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()
})
复制代码
这样在所有的路由中,res都具有一个cc方法,可以方便的向客户端输出结果。
优化表单验证
表单验证,前端为辅,后端为主,永远不相信前端提交的数据
1.安装包
1.安装joi包,为表单项定义验证规则
npm i joi
复制代码
安装@escook/express-joi,实现自动验证表单数据
npm i @escook/express-joi
复制代码
2.验证规则
新建schema/auth.js用户验证规则模块
mkdir schema
touch schema/auth.js
复制代码
初始化如下:
//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
}
}
复制代码
4.插入验证中间件
引入验证中间件
//引入验证中间件
const expressJoi = require('@escook/express-joi') //(*)
复制代码
引入验证规则
//引入验证规则
const { reg_login_schema } = require('../schema/auth')//(*)
复制代码
注册验证中间件
//用户注册路由,添加验证中间件
router.post('/register', expressJoi(reg_login_schema), authHandler.authRegister) //(*)
复制代码
修改后的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
复制代码
注意以上代码中(*)处是修改的地方。
5.捕获验证错误
在app.js中创建并注册全局错误处理中间件,用于处理验证错误(也可以处理其他错误)。
引入验证规则
//引入验证规则模块
const joi = require('joi')
复制代码
创建并注册全局异常中间件
//引入验证规则模块
const joi = require('joi')//注册异常捕获中间件server.use((err, req, res, next) => { if (err instanceof joi.ValidationError) return res.cc(err) res.cc(err)})
复制代码
6.验证测试
登录
1.登录步骤
表单验证;
数据查询;
密码比较;
生成JWT的Token字符串
2.表单验证
修改router/auth.js的路由如下:
//用户登录路由
router.post('/login', expressJoi(reg_login_schema), authHandler.authLogin)
复制代码
3.数据查询
在router_handler/auth.js中的登录处理方法中:
表单数据接收
const userinfo = req.body
复制代码
定义SQL语句
const sqlStr = 'select * from t_users where username=?'
复制代码
执行查询SQL
//执行查询
db.query(sqlStr, userinfo.username, (err, results) => {
//查询失败
if (err) return res.cc(err)
//查询结果不合理
if (results.length !== 1) return res.cc("登录失败")
//TODO:判断密码
})
复制代码
4.密码比较
调用bcrypt.compreSync(表单密码,数据库密码)判断密码是否一致,true一致,false不一致
//判断密码
const cmpRes = bcrypt.compare(userinfo.password, results[0].password)
if (!cmpRes) return res.cc('Login Failed')
//TODO:登录成功,生成token
复制代码
5.生成token
从查询结果中剔除password和avatar两个值
const usr = { ...results[0], password: '', avatar: '' }
复制代码
安装jwt
npm i jsonwebtoken
复制代码
在router_handler/auth.js中导入jwt
const jwt = require('jsonwebtoken')
复制代码
根目录创建配置文件config.js,并共享jwtSecretKey字符串(用于加密)
//config.js
module.exports = {
//一个复杂字符串
jwtSecretKey: "alkjflasngaoieakgbnasdfzxfgasdf",
expiresIn: '24h',//token有效期24h
}
复制代码
加密用户信息,生成token
//导入config
const config = require('../config')
//生成token
const tokenStr = jwt.sign(usr, config.jwtSecretKey, {
expiresIn: config.expiresIn,//token有效期为24小时
})
复制代码
返回客户端
res.send({
status: 200,
message: 'login success',
token: 'Bearer ' + tokenStr
})
复制代码
测试登录
6.Token解析
安装express-jwt模块(注意版本,较新版本不适合本教程)
npm i express-jwt@5.3.3
复制代码
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\//] }))
复制代码
app.js中token认证失败异常捕捉
if (err.name === 'UnauthorizedError') return res.cc('认证失败')
复制代码
解析验证
访问非/api开头的路由即可,这里使用/my
想要验证成功,需要在Header中加入Authorization字段,字段的值是登录时返回的Token:
获取用户信息
用户中心功能的一部分,获取用户个人信息,使用/my/info路由的GET请求。
1.基本步骤
初始化个人中心路由“router/my.js”
初始化路由处理函数“router_handler/my.js”
获取用户信息
2.初始化/router/my.js
创建文件router/my.js,编辑代码如下:
// 引入express模块
const express = require('express')
//创建路由对象
const router = express.Router()
//挂接/info路由
router.get('/info', (req, res) => {
res.send('ok')
})
//向外分享路由对象
module.exports = router
复制代码
在app.js中导入当前路由模块(可以紧贴/api/auth路由向后写)
//导入路由
const myRouter = require('./router/my')
//注册/my路由
server.use('/my', myRouter)
复制代码
3.测试路由配置
访问/api/auth/login登录并获取token
复制返回的token字符串。
访问/my/info
如果你和我的编码相同,返回ok即为正确。
4.初始化/router_handler/my.js
新建/router_handler/my.js文件,编辑内容如下:
//暴露/my/info路由的处理函数
exports.getInfo = (req, res) => {
res.send('/my/info handler')
}
复制代码
修改/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
复制代码
注意上述代码中(*)处的改动。
测试路由处理函数
如果返回的内容和我一样就没有问题了。
5.获取用户信息
导入/db/index模块
const db = require('../db/index')
复制代码
编写SQL语句
const sql = 'select id,username,nickname,email,avatar from t_users where id=?'
复制代码
执行查询语句
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]
})
});
复制代码
6.测试
这样就执行成功了。
更新用户信息
使用/my/info的POST请求更新用户个人信息。
1.实现步骤
定义路由
验证表单数据
更新用户信息
2.定义路由和处理函数
在/router/my.js中新增POST路由
//更新信息
router.post('/info', myHandler.setInfo)
复制代码
添加处理函数
//router_handler/my.js
//设置用户信息
exports.setInfo = (req, res) => {
res.rend('post /my/info handler')
}
复制代码
测试路由
3.参数验证
定义验证规则
新建/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
}
}
复制代码
引入验证中间件
在/router/my.js中引入express-joi中间件
// 引入验证中间件
const express_joi = require('@escook/express-joi')
复制代码
引入验证规则
在/router/my.js中引入joi验证规则
// 引入验证规则
const { update_info_schema } = require('../schema/my')
复制代码
在/my/info的POST路由添加验证
//更新信息
router.post('/info', express_joi(update_info_schema), myHandler.setInfo)
复制代码
验证测试
如果我们不提供id参数,就会报如下错误。
如果我们提供正确的参数,将获得如下结果:
源码链接(免积分、不付费)
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/)
Powered by Discuz! X3.4