当前位置: 首页 > news >正文

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&#xff0c;现更新为 点击build -》 build bundle -》build apk&#xff0c;项目报 Could not determine the dependencies of task :app:compileDebugUnitTestJavaWithJavac. > Could not resolve all task dependencies for configur…...

【慕伏白教程】 Linux 深度学习服务器配置指北

文章目录 镜像烧录系统安装系统配置常用包安装 镜像烧录 下载 Ubuntu 镜像 Ubuntu 桌面版 下载烧录工具 balenaEtcher 准备至少 8G 的 空白U盘 开始烧录 系统安装 开机进入BIOS&#xff0c;修改U盘为第一启动 选择 Try or Install Ubuntu 往下拉&#xff0c;选择 中文&a…...

学习windows系统让python脚本在后台运行的方法

学习windows系统让python脚本在后台运行的方法 windows 后台运行并输出日志文件windows 前台运行并输出日志文件 windows 后台运行并输出日志文件 命令&#xff1a; python qipa250.py >> qipa250_logs.log 2>&1 &窗口关闭后程序也就关闭了 windows 前台运…...

华为OD机试 - 第k个排列 - 全排列递归(Java 2023 B卷 100分)

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;A卷B卷&#…...

流媒体播放器EasyPlayer.js无法播放H.265的情况是什么原因?该如何解决?

H5无插件流媒体播放器EasyPlayer属于一款高效、精炼、稳定且免费的流媒体播放器&#xff0c;可支持多种流媒体协议播放&#xff0c;可支持H.264与H.265编码格式&#xff0c;性能稳定、播放流畅&#xff0c;能支持WebSocket-FLV、HTTP-FLV&#xff0c;HLS&#xff08;m3u8&#…...

负载均衡器监控

什么是负载均衡器 负载均衡建立在现有网络结构之上&#xff0c;它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。其意思就是分摊到多个操作单元上进行执行&#xff0c;例如Web服务器、FTP服务器、企…...

【计算机视觉】2.图像特征提取

图像特征提取 一、颜色特征量化颜色直方图聚类颜色直方图 二、边缘特征边缘边缘定义边缘提取边缘精细 三、特征点的特征描述子Harris角点FAST角点斑点SIFTHaar-like特征SURFORBLBPGabor 一、颜色特征 量化颜色直方图 HSV空间 优势&#xff1a;计算高效 劣势&#xff1a;量化问…...

华为存储培训

01 存储前沿技术和发展趋势 狭义的存储定义 CD、DVD、ZIP、磁带、硬盘等 广义的存储定义 存储硬件系统&#xff08;磁盘阵列&#xff0c;控制器&#xff0c;磁盘柜&#xff0c;磁带库等&#xff09; 存储软件&#xff08;备份软件&#xff1b;管理软件&#xff0c;快照&…...

I帧、P帧,B帧,GOP

doGetNextFrame() 在Live555库的FramedSource类中&#xff0c;数据帧的获取位置由doGetNextFrame()函数来设置。这个函数是一个虚函数&#xff0c;子类可以重写它以实现特定类型的数据帧获取逻辑。 在FramedSource的子类中&#xff0c;你可以重写doGetNextFrame()函数&#x…...

Apache DolphinScheduler在中国信通院“2023 OSCAR开源尖峰案例”评选中荣获「尖峰开源项目奖」!

在近日由中国信息通信研究院&#xff08;以下简称“中国信通院”&#xff09;和中国通信标准化协会联合主办的“2023 OSCAR 开源产业大会”上&#xff0c;主办方公布了 2023 年“OSCAR 开源尖峰案例”评选结果&#xff0c;包括“开源人物”“开源项目”“开源社区”“开源企业”…...

Java Lambda 表达式

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; Java Lambda 表达式 Java Lambda 表达式是 Java 8 引入的一种函数式编程特性&#xff0c;它是一种轻量级的匿名函数&#xff0c;允许我们将函数作为方法的参数进行传递…...

数据结构--插入排序

目录 插入排序 算法实现 算法效率分析 插入排序的优化-折半插入排序 最终的结果&#xff1a;&#xff08;方式&#xff09; 优化-折半查找的代码实现 ​回顾 插入排序 算法实现 算法效率分析 空间复杂度和问题规模无关 插入排序的优化-折半插入排序 之前的元素有序&am…...

服务器搭建(TCP套接字)-epoll版(服务端)

epoll 是一种在 Linux 系统上用于高效事件驱动编程的 I/O 多路复用机制。它相比于传统的 select 和 poll 函数具有更好的性能和扩展性。 epoll 的主要特点和原理&#xff1a; 1、事件驱动&#xff1a;epoll 是基于事件驱动的模型&#xff0c;它通过监听事件来触发相应的回调函…...

第一章:最新版零基础学习 PYTHON 教程(第十八节 - Python 表达式语句–Python 中的中断、继续和传递)

在 Python 中使用循环可以高效地自动执行和重复任务。但有时,可能会出现您想要完全退出循环、跳过迭代或忽略该条件的情况。这些可以通过循环控制语句来完成。循环控制语句改变其正常顺序的执行。当执行离开作用域时,在该作用域中创建的所有自动对象都将被销毁。Python支持以…...

Spring Cloud Alibaba Ribbon负载均衡器

文章目录 Ribbon 负载均衡器环境搭建1.依赖2.配置3.修改其默认的负载均衡策略3.1 验证 4.创建自定义的Rule4.1 MyRule&#xff08;&#xff09;4.2 在配置config类中配置 5.饥饿加载6.我只想访问不想被别的访问 Ribbon 负载均衡器 背景 Ribbon 是一个用于客户端负载均衡的开源…...

ardupilot开发 ---传感器驱动,外设驱动篇

ardupilot支持不同厂商的传感器&#xff0c;如雷达&#xff0c;声呐&#xff0c;激光&#xff0c;相机等&#xff1b; 支持的通信协议 I2C, SPI, UART (aka Serial) CANBUS 驱动程序的前后台分离 ardupilot中传感器驱动的重要结构是前后分离&#xff1b; 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 去重的几种方法

&#x1f514;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]&#x1f514;TreeSet去重 import java.util.TreeSet;TreeSet<Integer> set new T…...

UNet网络制作

UNet网络制作 代码参考UNet数据集制作及代码实现_哔哩哔哩_bilibili&#xff0c;根据该UP主的代码&#xff0c;加上我的个人整理和理解。&#xff08;这个UP主的代码感觉很好&#xff0c;很规范 UNet网络由三部分组成&#xff1a;卷积块&#xff0c;下采样层&#xff0c;上采样…...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

IT供电系统绝缘监测及故障定位解决方案

随着新能源的快速发展&#xff0c;光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域&#xff0c;IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选&#xff0c;但在长期运行中&#xff0c;例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具

第2章 虚拟机性能监控&#xff0c;故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令&#xff1a;jps [options] [hostid] 功能&#xff1a;本地虚拟机进程显示进程ID&#xff08;与ps相同&#xff09;&#xff0c;可同时显示主类&#x…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

Windows安装Miniconda

一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...