nodeJs+jwt实现小程序tonken鉴权
nodeJs+jwt实现小程序tonken鉴权
自我记录
config\config.js
// 配置文件
module.exports = {DBHOST: '127.0.0.1',DBPORT: '27017',DBNAME: 'test',secret: 'xxxxx',// 小程序的appSecretAppID: 'xxxxx',// 小程序的appId
}
token中间件
middlewares\checkTokenMiddleware.js
//导入 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})}//校验 tokenconst 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
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
//导入 用户的模型
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 });// 判断 dataif (!data) {return res.json({code: 400,msg: '用户名或密码错误',data: null});}// 创建当前用户的 tokenconst token = await getToken(data.openId, data.id)// 响应 tokenres.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 {// 销毁 tokenawait 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
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
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.usertry {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.usertry {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 });}
}
声明文档
// 导入 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
效果图


相关文章:
nodeJs+jwt实现小程序tonken鉴权
nodeJsjwt实现小程序tonken鉴权 自我记录 config\config.js // 配置文件 module.exports {DBHOST: 127.0.0.1,DBPORT: 27017,DBNAME: test,secret: xxxxx,// 小程序的appSecretAppID: xxxxx,// 小程序的appId }token中间件 middlewares\checkTokenMiddleware.js //导入 jwt…...
更新andriod studio版本,项目编译报could not find org.junit.jupiter:junit-jupiter
原本使用Android Studio 版本是4.1.1,现更新为 点击build -》 build bundle -》build apk,项目报 Could not determine the dependencies of task :app:compileDebugUnitTestJavaWithJavac. > Could not resolve all task dependencies for configur…...
【慕伏白教程】 Linux 深度学习服务器配置指北
文章目录 镜像烧录系统安装系统配置常用包安装 镜像烧录 下载 Ubuntu 镜像 Ubuntu 桌面版 下载烧录工具 balenaEtcher 准备至少 8G 的 空白U盘 开始烧录 系统安装 开机进入BIOS,修改U盘为第一启动 选择 Try or Install Ubuntu 往下拉,选择 中文&a…...
学习windows系统让python脚本在后台运行的方法
学习windows系统让python脚本在后台运行的方法 windows 后台运行并输出日志文件windows 前台运行并输出日志文件 windows 后台运行并输出日志文件 命令: python qipa250.py >> qipa250_logs.log 2>&1 &窗口关闭后程序也就关闭了 windows 前台运…...
华为OD机试 - 第k个排列 - 全排列递归(Java 2023 B卷 100分)
目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试(JAVA)真题(A卷B卷&#…...
流媒体播放器EasyPlayer.js无法播放H.265的情况是什么原因?该如何解决?
H5无插件流媒体播放器EasyPlayer属于一款高效、精炼、稳定且免费的流媒体播放器,可支持多种流媒体协议播放,可支持H.264与H.265编码格式,性能稳定、播放流畅,能支持WebSocket-FLV、HTTP-FLV,HLS(m3u8&#…...
负载均衡器监控
什么是负载均衡器 负载均衡建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企…...
【计算机视觉】2.图像特征提取
图像特征提取 一、颜色特征量化颜色直方图聚类颜色直方图 二、边缘特征边缘边缘定义边缘提取边缘精细 三、特征点的特征描述子Harris角点FAST角点斑点SIFTHaar-like特征SURFORBLBPGabor 一、颜色特征 量化颜色直方图 HSV空间 优势:计算高效 劣势:量化问…...
华为存储培训
01 存储前沿技术和发展趋势 狭义的存储定义 CD、DVD、ZIP、磁带、硬盘等 广义的存储定义 存储硬件系统(磁盘阵列,控制器,磁盘柜,磁带库等) 存储软件(备份软件;管理软件,快照&…...
I帧、P帧,B帧,GOP
doGetNextFrame() 在Live555库的FramedSource类中,数据帧的获取位置由doGetNextFrame()函数来设置。这个函数是一个虚函数,子类可以重写它以实现特定类型的数据帧获取逻辑。 在FramedSource的子类中,你可以重写doGetNextFrame()函数&#x…...
Apache DolphinScheduler在中国信通院“2023 OSCAR开源尖峰案例”评选中荣获「尖峰开源项目奖」!
在近日由中国信息通信研究院(以下简称“中国信通院”)和中国通信标准化协会联合主办的“2023 OSCAR 开源产业大会”上,主办方公布了 2023 年“OSCAR 开源尖峰案例”评选结果,包括“开源人物”“开源项目”“开源社区”“开源企业”…...
Java Lambda 表达式
💗wei_shuo的个人主页 💫wei_shuo的学习社区 🌐Hello World ! Java Lambda 表达式 Java Lambda 表达式是 Java 8 引入的一种函数式编程特性,它是一种轻量级的匿名函数,允许我们将函数作为方法的参数进行传递…...
数据结构--插入排序
目录 插入排序 算法实现 算法效率分析 插入排序的优化-折半插入排序 最终的结果:(方式) 优化-折半查找的代码实现 回顾 插入排序 算法实现 算法效率分析 空间复杂度和问题规模无关 插入排序的优化-折半插入排序 之前的元素有序&am…...
服务器搭建(TCP套接字)-epoll版(服务端)
epoll 是一种在 Linux 系统上用于高效事件驱动编程的 I/O 多路复用机制。它相比于传统的 select 和 poll 函数具有更好的性能和扩展性。 epoll 的主要特点和原理: 1、事件驱动:epoll 是基于事件驱动的模型,它通过监听事件来触发相应的回调函…...
第一章:最新版零基础学习 PYTHON 教程(第十八节 - Python 表达式语句–Python 中的中断、继续和传递)
在 Python 中使用循环可以高效地自动执行和重复任务。但有时,可能会出现您想要完全退出循环、跳过迭代或忽略该条件的情况。这些可以通过循环控制语句来完成。循环控制语句改变其正常顺序的执行。当执行离开作用域时,在该作用域中创建的所有自动对象都将被销毁。Python支持以…...
Spring Cloud Alibaba Ribbon负载均衡器
文章目录 Ribbon 负载均衡器环境搭建1.依赖2.配置3.修改其默认的负载均衡策略3.1 验证 4.创建自定义的Rule4.1 MyRule()4.2 在配置config类中配置 5.饥饿加载6.我只想访问不想被别的访问 Ribbon 负载均衡器 背景 Ribbon 是一个用于客户端负载均衡的开源…...
ardupilot开发 ---传感器驱动,外设驱动篇
ardupilot支持不同厂商的传感器,如雷达,声呐,激光,相机等; 支持的通信协议 I2C, SPI, UART (aka Serial) CANBUS 驱动程序的前后台分离 ardupilot中传感器驱动的重要结构是前后分离; Library库调用前端…...
二叉树的存储
目录 1.使用孩子表示法创建二叉树 2.二叉树的遍历 2.1前中后序遍历 2.2 前中后序遍历的选择题 2.3实现前中后序遍历 2.3.1前序遍历 2.3.2中序遍历 2.3.3后序遍历 3.二叉树的基本操作 3.1获取叶子节点的个数 3.2获取树中节点的个数 3.3获取第K层节点的个数 3.4获取…...
List 去重的几种方法
🔔HashSet去重 import java.util.HashSet;HashSet<Integer> set new HashSet<>(); set.add(1); set.add(2); set.add(2); System.out.println(set); // [1, 2]🔔TreeSet去重 import java.util.TreeSet;TreeSet<Integer> set new T…...
UNet网络制作
UNet网络制作 代码参考UNet数据集制作及代码实现_哔哩哔哩_bilibili,根据该UP主的代码,加上我的个人整理和理解。(这个UP主的代码感觉很好,很规范 UNet网络由三部分组成:卷积块,下采样层,上采样…...
深入解析 snprintf 和 vsnprintf:安全格式化字符串的最佳实践
1. 为什么需要安全的字符串格式化 在C语言开发中,字符串格式化是最基础也最容易出问题的操作之一。我见过太多因为格式化字符串不当导致的缓冲区溢出漏洞,轻则程序崩溃,重则成为安全攻击的入口点。传统的sprintf函数就像个不设防的大门&#…...
实战应用:基于快马平台开发具备origin高级分析功能的在线工具
今天想和大家分享一个最近用InsCode(快马)平台做的实战项目——开发一个具备Origin高级分析功能的在线工具。作为一个经常需要处理实验数据的科研狗,Origin这类软件的分析功能确实强大,但每次都要安装本地软件实在麻烦。于是就想试试能不能做个在线版&am…...
嵌入式AI新篇章:Qwen3-ASR-0.6B在边缘计算设备上的部署与优化
嵌入式AI新篇章:Qwen3-ASR-0.6B在边缘计算设备上的部署与优化 1. 引言:当语音识别遇见边缘计算 想象一下,你对着一个巴掌大的智能音箱说话,它几乎在你话音落下的瞬间就理解了你的意思,并且完全不需要连接云端。或者&…...
鸿蒙与Android双端蓝牙开发避坑指南:定位权限、虚拟地址与厂商SDK那些事
鸿蒙与Android双端蓝牙开发实战:权限策略与真实地址获取全解析 当你的应用需要同时在鸿蒙和Android设备上稳定运行蓝牙功能时,系统差异就像一片雷区——Android 12的权限拆分、鸿蒙4.0的虚拟地址返回、不同版本间的API兼容性,每个环节都可能让…...
计算机毕业设计springboot基于Web的健身会员管理系统 基于SpringBoot的健身房智能化运营服务平台 SpringBoot框架下的健身俱乐部会员服务与课程预约系统
计算机毕业设计springboot基于Web的健身会员管理系统e7cr4n62(配套有源码 程序 mysql数据库 论文) 本套源码可以在文本联xi,先看具体系统功能演示视频领取,可分享源码参考。 随着全民健身意识的提升和健康管理需求的日益增长,传统…...
炉石传说自动化脚本终极指南:从3小时到3分钟的游戏体验革命
炉石传说自动化脚本终极指南:从3小时到3分钟的游戏体验革命 【免费下载链接】Hearthstone-Script Hearthstone script(炉石传说脚本)(2024.01.25停更至国服回归) 项目地址: https://gitcode.com/gh_mirrors/he/Heart…...
像素幻梦效果对比:原生FLUX.1-dev vs 像素幻梦定制版输出质量分析
像素幻梦效果对比:原生FLUX.1-dev vs 像素幻梦定制版输出质量分析 1. 引言 在数字艺术创作领域,像素艺术因其独特的复古美感和现代应用价值而备受关注。Pixel Dream Workshop(像素幻梦)作为基于FLUX.1-dev模型构建的专业像素艺术…...
三步掌握开源资源处理工具:让RPG Maker MV资源处理效率提升90%
三步掌握开源资源处理工具:让RPG Maker MV资源处理效率提升90% 【免费下载链接】RPG-Maker-MV-Decrypter You can decrypt RPG-Maker-MV Resource Files with this project ~ If you dont wanna download it, you can use the Script on my HP: 项目地址: https:/…...
uniapp 如何实现google登录-安卓端
uniapp 如何实现google登录-安卓端 本文只讲解uniapp安卓端如何获取到idToken来实现登录,ios使用uniapp官方方法可以获取 海外app貌似最常用的就是邮箱登录,在app上表现出来最常用的就是谷歌一键登录,或者邮箱加网页验证;google登…...
s2-proGPU利用率提升方案:批处理合成与异步请求性能压测报告
s2-pro GPU利用率提升方案:批处理合成与异步请求性能压测报告 1. 项目背景与挑战 s2-pro作为Fish Audio开源的专业级语音合成模型镜像,在实际应用中面临GPU利用率不足的问题。通过初步监测发现: 单次请求GPU利用率峰值仅达到35-40%请求间隔…...
