目录
相关网站
接口文档
后台API接口文档https://www.showdoc.com.cn/escook?page_id=3707158761215217接口服务文档
项目指导 api_server_evhttp://escook.cn:8088/#/
黑马程序员Node.js全套入门教程---bilibilihttps://www.bilibili.com/video/BV1a34y167AZ?p=82
代码展示
根目录为 api_server
app.js
const express = require('express')
// 创建服务器实例
const app = express()
const joi = require('joi')
// 导入并配置 cors 中间件
const cors = require('cors')
app.use(cors())
// 配置解析表单数据的中间件,只能解析 application/x-www-form-urlencoded 格式的表单数据
app.use(express.urlencoded({ extended: false }))
// 一定要在路由前封装 rec.cc 函数
app.use(function (req,res,next) {
// status=0成功,1失败;默认为1
res.cc = function (err, status = 1) {
res.send({
// 状态
status,
// 状态描述,判断 err 是 错误对象 还是 字符串
message: err instanceof Error ? err.message : err,
})
}
next()
})
const expressJwt = require('express-jwt')
const config = require('./config')
app.use(expressJwt({secret:config.jwtSecretKey}).unless({path:[/^\/api/]}))
// 导入并使用用户路由模块
const userRouter = require('./router/user')
app.use('/api',userRouter)
// 错误级别中间件
app.use((err, req, res, next) => {
// 验证失败
if (err instanceof joi.ValidationError) return res.cc(err)
// 认证失败
if (err.name === 'UnauthorizedError') return res.cc('身份认证失败!')
// 未知错误
res.cc(err)
})
app.listen(3007,() => {
console.log('http://127.0.0.1:3007');
})
/db/index.js
const mysql = require('mysql')
const db = mysql.createPool({
host: '127.0.0.1',
user:'root',
password: 'admin',
database: 'my_db_01',
})
module.exports = db
/router/user.js
const joi = require("joi");
/**
* string() 值必须是字符串
* alphanum() 值只能是包含 a-zA-Z0-9 的字符串
* min(length) 最小长度
* max(length) 最大长度
* required() 值是必填项,不能为 undefined
* pattern(正则表达式) 值必须符合正则表达式的规则
*/
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,
},
};
/router_handler/user.js
const db = require('../db/index')
const bcrypt = require('bcryptjs')
const jwt = require('jsonwebtoken')
const config = require('../config.js')
// 注册处理函数
exports.regUser = (req,res) => {
const userinfo = req.body
// if (!userinfo.username || !userinfo.password) {
// // return res.send({ status:1, message:'用户名或密码不能为空!!!'})
// return res.cc('用户名或密码不能为空!!!')
// } // 替换为第三方库中间件验证
// 查重
const sqlStr = 'select * from ev_users where username=?'
db.query(sqlStr, [userinfo.username], function(err,results) {
if (err) {
// return res.send({ status: 1, message: err.message })
return res.cc(err)
}
if (results.length >0 ) {
// return res.send({ status:1, message:'用户名被占用,请更换!'})
return res.cc('用户名被占用,请更换!')
}
// 密码加密
userinfo.password = bcrypt.hashSync(userinfo.password, 10)
// 插入新用户
const sqlStr = 'insert into ev_users set ?'
db.query(sqlStr, {username: userinfo.username, password: userinfo.password}, (err,results) => {
// if (err) return res.send({status:1, message:err.message})
if (err) return res.cc(err)
// if (results.affectedRows !==1 ) return ({status:1,message:'注册失败!'})
if (results.affectedRows !==1 ) return res.cc('注册失败!')
// res.send({ status:0, message:'注册成功!' })
res.cc('注册成功!',0 )
})
})
}
// 登录处理函数
exports.login = (req,res) => {
const userinfo = req.body
// 判断是否存在用户名
const sql = 'select * from ev_users where username=?'
db.query(sql, userinfo.username, function (err,results) {
if (err) return res.cc(err)
if (results.length !== 1 ) return res.cc('登录失败!')
// 密码对比
const compareResult = bcrypt.compareSync(userinfo.password, results[0].password)
if (!compareResult) {
return res.cc('登陆失败!')
}
const user = {...results[0], password:'', user_pic:''}
// 对用户信息加密
const tokenStr = jwt.sign(user, config.jwtSecretKey, {expiresIn: config.expiresIn})
res.send({
status:0,
message: '登录成功!',
token: 'Bearer ' + tokenStr,
})
})
}
/schema/user.js
const joi = require("joi");
/**
* string() 值必须是字符串
* alphanum() 值只能是包含 a-zA-Z0-9 的字符串
* min(length) 最小长度
* max(length) 最大长度
* required() 值是必填项,不能为 undefined
* pattern(正则表达式) 值必须符合正则表达式的规则
*/
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,
},
};
config.js
module.exports = {
jwtSecretKey: 'aasdasd',
expiresIn: '10h',
}
package.json
{
"name": "api_server",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@escook/express-joi": "^1.1.1",
"bcryptjs": "^2.4.3",
"cors": "^2.8.5",
"express": "^4.17.1",
"express-jwt": "^5.3.3",
"joi": "^17.6.0",
"jsonwebtoken": "^8.5.1",
"mysql": "^2.18.1"
},
"devDependencies": {
"nodemon": "^2.0.15"
}
}
第三方模块的作用
"@escook/express-joi": @escook/express-joi - npm (npmjs.com) 验证规则
"bcryptjs": 加密
"cors": " 跨域
"express-jwt": 解析 jwt (json web token)
"joi": 数据验证器
"jsonwebtoken": 跨域认证解决方案
"mysql": 数据库
bug处理
密码验证 joi版本错误