nodeJs+jwt实现小程序tonken鉴权
自我记录
config\config.js
ts
// 配置文件
module.exports = {
DBHOST: '127.0.0.1',
DBPORT: '27017',
DBNAME: 'test',
secret: 'xxxxx',// 小程序的appSecret
AppID: 'xxxxx',// 小程序的appId
}
token中间件
middlewares\checkTokenMiddleware.js
ts
//导入 jwt
const jwt = require('jsonwebtoken');
//读取配置项
const {secret} = require('../config/config');
//声明中间件
module.exports = (req, res, next) => {
//获取 token 采用的是 Bearer + ' ' + token形式
const Authorization = req.get('Authorization');
//判断
if (!Authorization) {
return res.json({
code: 401,
msg: '暂无权限',
data: null
})
}
//校验 token
const token = Authorization.split(' ')[1]
jwt.verify(token, secret, (err, data) => {
//检测 token 是否正确
if (err) {
return res.json({
code: 403,
msg: 'token失效',
data: null
})
}
//保存用户的信息
req.user = data; // req.session req.body
//如果 token 校验成功
next();
});
}
routes路由文件
routes\user.js
ts
const express = require('express');
const router = express.Router();
//导入 用户路由函数
const user_handler = require('../router_handler/user');
// 注册新用户
router.post('/reguser', user_handler.reguser);
//登录操作TODO
router.post('/login', user_handler.login);
//退出登录TODO
router.post('/logout',user_handler.logout );
module.exports = router;
user路由函数
router_handler\user.js
ts
//导入 用户的模型
const UserModel = require('../models/UserModel');
//导入配置文件
const { secret, AppID } = require('../config/config')
//导入 jwt
const jwt = require('jsonwebtoken');
//导入请求
const request = require('request')
//导入 shortid
const shortid = require('shortid');
//注册用户
exports.reguser = async (req, res) => {
try {
const js_code = req.body.code;
if (!js_code) {
return res.json({
code: 400,
message: '缺少 js_code 参数'
});
}
// 发送请求并处理响应
sendRequest(js_code, handleResponse(res));
} catch (err) {
console.error('Error registering user:', err);
res.json({
code: 400,
msg: '注册失败,请稍后再试~~',
data: null
});
}
}
const sendRequest = (js_code, callback) => {
request(`https://api.weixin.qq.com/sns/jscode2session?appid=${AppID}&secret=${secret}&js_code=${js_code}&grant_type=authorization_code`, callback);
}
const handleResponse = (res) => {
return async (error, response, body) => {
if (error) {
console.error('Error sending request:', error);
return res.json({
code: 500,
message: '请求失败,请稍后再试~~'
});
}
if (response.statusCode !== 200) {
return res.json({
code: 400,
message: '获取用户信息失败'
});
}
try {
const bodyInfo = JSON.parse(body);
const openId = bodyInfo.openid;
if (!openId) {
return res.json({
code: 400,
msg: 'code失效',
data: null
});
}
const userData = await UserModel.findOne({ openId });
if (userData) {
const token = await getToken(userData.openId, userData.id)
const result = await UserModel.updateOne({ id: userData.id }, { token: token })
if (!result.acknowledged) {
throw new Error('写入操作未被确认');
}
return res.json({
code: 200,
msg: '该用户已存在并生成新的token',
data: token
});
}
const id = shortid.generate()
const token = await getToken(openId, id)
const data = await UserModel.create({ openId, token, id });
res.json({
code: 200,
msg: '获取成功',
data: data.token
});
} catch (err) {
console.error('Error registering user:', err);
res.json({
code: 400,
msg: '注册失败,请稍后再试~~',
data: null
});
}
};
}
// 创建当前用户的 token
const getToken = async (openId, id) => {
return await jwt.sign({
openId,
id
}, secret, {
expiresIn: 60 * 60 * 24 * 7
});
}
// 登录待测试
exports.login = async (req, res) => {
try {
// 获取用户名和密码
const { openId } = req.body;
// 查询数据库
const data = await UserModel.findOne({ openId });
// 判断 data
if (!data) {
return res.json({
code: 400,
msg: '用户名或密码错误',
data: null
});
}
// 创建当前用户的 token
const token = await getToken(data.openId, data.id)
// 响应 token
res.json({
code: 200,
msg: '登录成功',
data: token
});
} catch (err) {
// 处理错误
console.error('Error logging in:', err);
res.json({
code: 500,
msg: '登录失败',
data: null
});
}
}
// 退出待测试
exports.logout = async (req, res) => {
try {
// 销毁 token
await new Promise((resolve, reject) => {
req.token.destroy((err) => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
// 响应退出成功
res.json({
code: 200,
msg: '退出成功',
data: null
});
} catch (err) {
// 处理错误
console.error('Error logging out:', err);
res.json({
code: 500,
msg: '退出失败',
data: null
});
}
}
权限相关
展示openId 对应用户的书籍信息
书籍路由文件
routes\book.js
ts
const express = require('express')
const router = express.Router()
// 导入路由函数
const book_handler = require('../router_handler/book')
// 导入验证token的中间件
const checkTokenMiddleware = require('../middlewares/checkTokenMiddleware')
// 一个路由的组成有 请求方法 , 路径 和 回调函数 组成
// app.<method>(path,callback)
// 注册新书籍
router.post('/addbook',checkTokenMiddleware, book_handler.addBook)
// 获取列表
router.get('/getBook',checkTokenMiddleware, book_handler.getBook);
// 获取单独的
router.get('/book/:id',checkTokenMiddleware, book_handler.getOneBook);
// 删除单独的
router.delete('/book/:id',checkTokenMiddleware, book_handler.delBook);
module.exports = router
书籍路由函数
router_handler\book.js
ts
const BookModel = require('../models/BookModel');
// 单条新增
exports.addBook = async (req, res) => {
try {
const data = await BookModel.create({
...req.body, user: req.user.openId
})
return res.json({ code: 200, message: "添加成功", data: data });
} catch (err) {
// 处理错误并打印错误信息
// 处理错误并返回失败的 JSON 响应
console.error("Error creating book:", err);
return res.json({ code: 500, message: "添加失败", error: err.message });
}
}
// 获取列表
exports.getBook = async (req, res) => {
try {
const data = await BookModel.find({ user: req.user.openId })
return res.json({ code: 200, message: "查询成功", data });
} catch (err) {
console.error("Error creating book:", err);
return res.json({ code: 500, message: "查询失败", error: err.message });
}
}
// 获取ID
exports.getOneBook = async (req, res) => {
let { id } = req.params;
let { openId } = req.user
try {
const data = await BookModel.findOne({ _id: id, user: openId })
if (!data) {
return res.json({ code: 404, message: "未找到匹配的书籍" });
}
return res.json({ code: 200, message: "查询成功", data });
} catch (err) {
console.error("Error creating book:", err);
return res.json({ code: 500, message: "查询失败", error: err.message });
}
}
// 删除ID
exports.delBook = async (req, res) => {
let { id } = req.params;
let { openId } = req.user
try {
const result = await BookModel.deleteOne({ _id: id, user: openId })
if (result.deletedCount === 1) {
// 成功删除
return res.json({ code: 200, message: "删除成功", data: {} });
} else {
// 没有匹配的文档
return res.json({ code: 404, message: "未找到匹配的文档" });
}
} catch (err) {
console.error("Error deleting book:", err);
return res.json({ code: 500, message: "删除失败", error: err.message });
}
}
声明文档
ts
// 导入 mongoose
const mongoose = require('mongoose')
// 创建文档的结构对象
// 设置集合中 文档的属性 以及类型值
let UserSchema = new mongoose.Schema({
openId: String, // 添加 openId 字段
token: String,
id: String,
});
// 创建模型对象 : mongoose 会使用集合的复数去创建集合
let UserModel = mongoose.model("users", UserSchema);
// 暴露模型对象
module.exports = UserModel
-------------------------------------------------------书籍相关----------------------------------
// 导入 mongoose
const mongoose = require('mongoose')
// 5. 创建文档的结构对象
// 设置集合中 文档的属性 以及类型值
let BookSchema = new mongoose.Schema({
name: {
type: String,
required: true, // 必填
unique: true // 独一无二 新集合才可以
},
author: {
type: String,
default: '匿名' // 默认值
},
gender: {
type: String,
enum: ['男', '女'] // 枚举 必须是里面的内容
},
price: Number,
is_hot: Boolean,
user: {
type: String, // 或者其他与用户标识匹配的类型
required: true
},
// tag: Array,
// pub_time: Date,
});
// 6.创建模型对象 : mongoose 会使用集合的复数去创建集合
let BookModel = mongoose.model("books", BookSchema);
// 暴露模型对象
module.exports = BookModel
效果图