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网络由三部分组成:卷积块,下采样层,上采样…...
uniapp 对接腾讯云IM群组成员管理(增删改查)
UniApp 实战:腾讯云IM群组成员管理(增删改查) 一、前言 在社交类App开发中,群组成员管理是核心功能之一。本文将基于UniApp框架,结合腾讯云IM SDK,详细讲解如何实现群组成员的增删改查全流程。 权限校验…...
(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
(二)TensorRT-LLM | 模型导出(v0.20.0rc3)
0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
Golang——9、反射和文件操作
反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一:使用Read()读取文件2.3、方式二:bufio读取文件2.4、方式三:os.ReadFile读取2.5、写…...
