# api-server **Repository Path**: huajiuZhao/api-server ## Basic Information - **Project Name**: api-server - **Description**: 基于node+express框架的api项目 - **Primary Language**: JavaScript - **License**: ISC - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2024-06-17 - **Last Updated**: 2025-06-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # express 项目创建 ## 初始化 ### 1.创建项目名称api-server ```html 可使用命令 mkdir api-server创建项目文件夹 ``` ### 2.进入api-server目录 ``` cd api-server ``` ### 3.初始化项目 ``` json npm init -y ``` ### 4.安装express ``` npm i express ``` ### 5.在项目api-server目录下,创建app.js文件 ```js //1.导入 express const express = require("express") //2.创建 express 服务 const app = express(); //4.导入 cors 跨域中间件 const cors = require("cors"); //4.1注册 cors() 中间件 app.use(cors()); //5.导入express内置的表单解析中间件 urlencoded x-www-form-urlencoded app.use(express.urlencoded({extended: false})); //6、导入路由模块并注册 const userRouter = require("./router/user") app.use('/api', userRouter); //3.启动服务 app.listen(3006, () => { console.log("server running at http://127.0.0.1:3006") }) ``` ## 登录、注册 ### 1.创建router目录,主要存放相关路由模块的映射关系文件 ### 2.在router目录下,创建user.js文件,存放用户相关接口映射 ```js const express = require("express"); //导入映射函数 const {login, regUser} = require("../router-handler/user"); const router = express.Router(); //定义用户注册接口 router.post("/register", regUser) //定义用户登录接口 router.post('/login', login) //导出路由 module.exports = router; ``` ### 3.创建router-handler目录,主要存放接口函数模块 ### 4.在router-handler目录下,创建 user.js 文件 ```js //导出并定义用户注册函数 exports.regUser = (req, res) => { res.send("register Ok") } //导出并定义用户登录函数 exports.login = (req, res) => { res.send("login ok") } ``` ### 5.安装数据库 ``` npm i mysql ``` ### 6.先创建db目录,再该目录下创建mysql.js文件 ```js //导入数据库mysql const mysql = require("mysql"); //创建数据库实例 const db = mysql.createConnection({ host: "127.0.0.1", //数据库IP user: "root", //数据库登录用户名 password: "admin123",//数据库登录密码 database: "my_db_01",//数据库名称 }) //导出数据 module.exports = db; ``` ### 7.在app.js 导入数据库模块并连接 ```js //7、导入mysql const db = require("./db/mysql"); db.connect();//连接数据库 //检测数据库 是否连接成功 db.query("SELECT 1", function (error, results) { if (error) throw error; console.log('The solution is: ', results); //The solution is: [ RowDataPacket { '1': 1 } ] }) ``` ### 8.打开MySql Workbench,创建my_db_01数据库,然后在数据库my_db_01下,创建ev_users用户信息表 ``` mysql -- 新增字段 id int username varchart(225) password varchart(225) email varchart(255) user_pic text -- sql语句 ALTER TABLE `my_db_01`.`en_users` CHANGE COLUMN `username` `username` VARCHAR(225) NOT NULL , CHANGE COLUMN `password` `password` VARCHAR(225) NOT NULL , CHANGE COLUMN `nickname` `nickname` VARCHAR(225) NULL DEFAULT NULL , CHANGE COLUMN `email` `email` VARCHAR(225) NULL DEFAULT NULL ; ``` ### 9.后台做表单校验 ``` //安装 npm i @escook/express-joi joi@17.4.0 ``` ### 10.创建schema目录,然后创建user.js ```js //导入验证规则的包 const Joi = require("joi") //定义用户名验证规则 const username = Joi.string().alphanum().min(1).max(10).required() //定义密码验证规则 const password = Joi.string().pattern(new RegExp('^[\S]{6,12}$')).required() //导出验证规则对象 exports.reg_login_schema = { body: { username, password } } ``` ### 11.打开router目录下的user.js文件,改造register接口 ```js //导入校验规则的包 const expressJoi = require("@escook/express-joi"); //导入需要验证规则 const {reg_login_schema} = require("../schema/user") //定义用户注册接口 router.post("/register", expressJoi(reg_login_schema), regUser) ``` ### 12.登录 ##### 12.1登录信息验证 ```javascript //定义用户登录接口 router.post('/login', expressJoi(reg_login_schema), login) ``` ##### 12.2接受客服端发送的数据,查询用户是否存在,判断密码是否正确,使用jsonwebtoken生成token字符串 ```javascript exports.login = (req, res) => { //接受客服端发送的数据 let userInfo = req.body; //查询用户是否存在 let sql = "SELECT * FROM en_users WHERE username = ?" db.query(sql, userInfo.username, (err, results) => { if (err) { return res.cc(err) } //判断用户是否存在 if (results.length === 0) { return res.cc("登录失败,用户名错误"); } //判断密码是否正确 let password = bcrypt.compareSync(userInfo.password, results[0].password); if (!password) { return res.cc("登录失败,密码错误") } //需要去掉用户的敏感信息,密码、头像等数据 let user = {...results[0], password: "", user_pic: ""} //生成token字符串,返回给客服端 let token = jwt.sign(user, jwtSecretKey, {expiresIn: expiresIn}); return res.send({ status: 0, message: "登录成功", token: "Bearer " + token }) }) } ``` ##### 12.3 使用express-jwt解析token 1.安装 ``` npm i express-jwt ``` 2.在app.js文件配置token解析中间件: ```javascript //导入express-jwt const {expressjwt: jwt} = require("express-jwt") //导入密钥解密 const {jwtSecretKey} = require("./config"); //9.在路由之前注册token解析校验, 正则处理/api/路径的接口不做token校验 app.use(jwt({secret: jwtSecretKey, algorithms: ['HS256']}).unless({path: [/^\/api/]})) //定义应用级别的错误中间件 app.use((err, req, res, next) => { //其他代码... //判断token身份验证 if (err.name === 'UnauthorizedError'){ return res.cc("身份验证失败") } }) ``` ### 个人中心 #### 3.获取用户信息 ##### 3.1实现步骤 1.在 /router/userinfo.js 模块,并初始化代码如下结构: ```js //导入express const express = require("express"); //创建Router实例 const router = express.Router(); //定义获取用户信息接口 router.get("/userinfo", (req, res) => { res("userinfo ok") }) //导出路由 module.exports = router; ``` 2.在 app.js 文件中,导入注册个人信息路由 ```js //导入个人信息路由模块并注册 const userInfoRouter = require("./router/userinfo") app.use("/my", userInfoRouter) ``` 3.在 router-handler/userinfo.js文件中,初始化代码如下结构: ```js //导入数据模块 const db = require("../db/mysql") //获取用户基础信息 exports.getUserInfo = (req, res) => { //定义查询sql let sql = "SELECT id,username,nickname,email,user_pic FROM en_users WHERE id = ?" //调用db.query()方法 执行sql语句 //从token中获取用户id db.query(sql, req.auth.id, (err, results) => { if (err) { return res.cc(err) } if (results.length !== 1) { return res.cc("用户信息获取失败") } res.send({ status: 0, message: "用户信息获取成功", data: results[0] }) }) } ``` #### 4.更新用户信息 ##### 4.1实现步骤 1.在 /router/userinfo.js 中,添加如下代码: ```js //定义更新用户信息接口 router.post("/updateUserInfo", updateUserInfo) ``` 2.在 router-handler/userinfo.js文件中,添加代码如下: ```js //更新用户信息接口 exports.updateUserInfo = (req, res) => { res.cc("ok", 0) } ``` 3.在 /schema/user.js 中,定义校验规则,代码如下: ```js //定义 id、nickname、email验证规则 const user_id = Joi.number().integer().min(1).required() //要求为数字类型、整数、最小为1、必填 const nick_name = Joi.string().required() //要求字符串、必填 const user_email = Joi.string().email().required() //要求字符串、邮箱格式、必填 //导出更新用户新的验证规则对象 exports.update_userInfo_schema = { body: { id: user_id, nickname: nick_name,//用 nick_name 规则去校验客服端提交的 nickname 数据是否要求 email: user_email,//用 user_email 规则去校验客服端提交的 email 数据是否要求 } } ``` 4.在 /router/userinfo.js 中,添加如下代码: ```js //导入express-joi模块 const expressJoi = require("@escook/express-joi"); //导入校验规则 const {update_userInfo_schema} = require("../schema/user"); //定义更新用户信息接口 调用expressJoi()方法 校验req.body的数据 router.post("/updateUserInfo", expressJoi(update_userInfo_schema), updateUserInfo) ``` 5.在 router-handler/userInfo.js 中,添加代码如下: ```js //更新用户信息接口 exports.updateUserInfo = (req, res) => { //定义更新sql let sql = "UPDATE en_users SET nickname = ?,email = ? WHERE id = ?" //调用db.query()方法,执行sql db.query(sql, [req.body.nickname, req.body.email, req.auth.id], (err, results) => { if (err) { return res.cc(err) } console.log(results) if (results.affectedRows !== 1) { return res.cc("用户信息更新失败") } res.send({ status: 0, message: "用户信息更新成功", data: req.body }) }) } ``` #### 5.修改用户密码 ##### 5.1实现步骤 1.在 router/userinfo.js 中,添加如下代码: ```js //定义修改用户密码接口 router.post("/updatePwd", expressJoi(pwd_schema), updateUserPwd) ``` 2.在 schema/user.js 中,添加如下代码: ```js //导出修改密码对象 exports.pwd_schema = { body: { password, old_password: Joi.not(Joi.ref('password')),//旧密码不能与新密码相同 repeat_password: Joi.ref('password'),//第一次与第二次输入的密码必须相同 } } ``` 3.在 router-handler/userInfo.js 中,添加如下代码: ```js //修改用户密码 exports.updateUserPwd = (req, res) => { //定义修改sql let sql = "UPDATE en_users SET password = ? WHERE id = ?" //定义sql判断旧密码是否正确 let sqlQuery = "SELECT password FROM en_users WHERE id = ?" db.query(sqlQuery, req.body.id, (err, results) => { if (err) { return res.cc(err) } if (results.length !== 1) { return res.cc("密码修改失败") } let isPassword = bcrypt.compareSync(req.body.old_password, results[0].password) if (!isPassword) { return res.cc("旧密码不正确") } //执行sql //密码加密 req.body.password = bcrypt.hashSync(req.body.password, 10); db.query(sql, [req.body.password, req.auth.id], (err, results) => { if (err) { return res.cc(err) } if (results.affectedRows !== 1) { return res.cc("密码修修改失败") } res.send({ status: 0, message: "密码修改成功", }) }) }) } ``` #### 6.修改用户头像 ##### 6.1实现步骤 1.在 router/userinfo.js 中,添加代码如下: ```js //定义修改头像 router.post("/updateAvatar", expressJoi(avatar_schema), updateAvatar) ``` 2.在 schema/user.js 中,添加如下代码: ```js const avatar = Joi.string().dataUri().required() //导出头像验证对象 exports.avatar_schema = { body: { avatar } } ``` 3.在 router-handler/userInfo.js 中,添加代码如下: ```js //修改用户头像 exports.updateAvatar = (req, res) => { //定义sql let sql = "UPDATE en_users SET user_pic = ? WHERE id = ?" db.query(sql, [req.body.avatar, req.auth.id], (err, results) => { if (err) { return res.cc(err) } if (results.affectedRows !== 1) { return res.cc("头像修改失败") } res.cc("头像修改成功", 0) }) } ``` ## 文章分类管理 #### 6.1创建 ev_article_cate 数据表,添加字段如下: Id INT name VARCHAR(255) alias VARCHAR(255) is_delete TINYINT(1) 0 //0 表示未删除 1 表示已删除 ## 依赖包版本及作用 ``` //用于把客服端提交的数据挂载到joi做校验 "@escook/express-joi": "^1.1.1", //用于用户密码加密 、密码判断是否正确 防止数据库泄漏时,导致用户信息被非法利用 "bcryptjs": "^2.4.3", //用户前后端分离 跨域问题 "cors": "^2.8.5", //express框架 "express": "^4.19.2", //用户解析token中的用户信息 "express-jwt": "^8.4.1", //用于定义表单校验规则 "joi": "^17.13.1", //用于把用户信息生成token "jsonwebtoken": "^9.0.2", //用户连接数据、操作数据库增、删、改、查 "mysql": "^2.18.1", //用户解析表单的文件上传 "multer":"^1.4.5-lts.1" //生成uuid "uuid": "^10.0.0" ```