当前位置: 首页 > 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;上采样…...

uniapp 对接腾讯云IM群组成员管理(增删改查)

UniApp 实战&#xff1a;腾讯云IM群组成员管理&#xff08;增删改查&#xff09; 一、前言 在社交类App开发中&#xff0c;群组成员管理是核心功能之一。本文将基于UniApp框架&#xff0c;结合腾讯云IM SDK&#xff0c;详细讲解如何实现群组成员的增删改查全流程。 权限校验…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心

当仓库学会“思考”&#xff0c;物流的终极形态正在诞生 想象这样的场景&#xff1a; 凌晨3点&#xff0c;某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径&#xff1b;AI视觉系统在0.1秒内扫描包裹信息&#xff1b;数字孪生平台正模拟次日峰值流量压力…...

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日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; 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、方式一&#xff1a;使用Read()读取文件2.3、方式二&#xff1a;bufio读取文件2.4、方式三&#xff1a;os.ReadFile读取2.5、写…...