react+koa+vite前后端模拟jwt鉴权过程
路由组件(生成token)
const Router = require('@koa/router')
const jwt = require('jsonwebtoken');
const router = new Router()const mockDbUserInfo = [{nickname: 'xxxliu',username: 'Tom',password: 123456,icon: 'url1'},{nickname: 'xxx',username: 'John',password: 123456,icon: 'url2'},
]const secretKey = 'xxxliu key';router.post('/api/home', async ctx => {ctx.response.body = {msg: '主页',code: 'success'}
})router.post('/api/login', async ctx => {try {const { username, password } = ctx.request.body;//mock查db操作const { nickname, password: pwd, icon } = mockDbUserInfo.find(item => item.username === username) || {};if (!nickname) {ctx.response.body = {msg: "不存在该用户",code: "failed",};return;}if (pwd !== password) {ctx.response.body = {msg: "密码输入错误",code: "error",};return;}// 构建 JWT 头部const header = {alg: 'HS256', // 签名算法,例如使用 HMAC SHA-256typ: 'JWT', // Token 的类型};const payload = {username};const options = {expiresIn: '1h', // 设置 JWT 的过期时间header, // 将 header 选项包含在 options 中};//生成tokenconst token = jwt.sign(payload, secretKey, options);ctx.response.body = {nickname,icon,code: "success",msg: "登录成功",};ctx.cookies.set('myToken',token,{ maxAge: 1 * 60 * 60 * 1000, httpOnly: false})} catch (error) {ctx.response.body = error;}
})module.exports = router;
token解析
const jwt = require('jsonwebtoken');const secretKey = 'xxxliu key';
const verifyToken = async (ctx, next) => {try {const { url } = ctx.request;//走登录页不鉴权const requestUrl = url.split("?")[0];const noVerifyList = ["/api/login"];const noVerify = noVerifyList.includes(requestUrl);if (noVerify) {await next();} else {//拿到请求头的参数const authorization = ctx.request.header["authorization"];const username = ctx.request.body["username"];if (authorization.startsWith('Bearer ')) {const token = authorization.slice(7);const { exp, username: userName } = jwt.verify(token, secretKey) || {};if (userName !== username) {ctx.response.body = {code: "error",msg: "无效的token, 请重新登录",};}else if (exp * 1000 > Date.now()) {ctx.response.body = {code: "error",msg: "登录信息已过期, 请重新登录",};} else {await next();}} else {ctx.response.body = {code: "error",msg: "无效的token, 请重新登录",};}}} catch (err) {if (err.name == "TokenExpiredError") {ctx.body = {code: "error",msg: "token已过期, 请重新登录",};} else if (err.name == "JsonWebTokenError") {ctx.body = {code: "error",msg: "无效的token, 请重新登录",};}}};module.exports = verifyToken;
注册中间件
const Koa = require('koa')
const path = require('path')
const sendfile = require('koa-sendfile')
const static = require('koa-static')
const bodyParser = require("koa-bodyparser")
const router = require('./server/api-router.js')
const assets = require('./server/assets-router')
const verifyToken = require('./server/verifyToken.js');
const app = new Koa()// static
app.use(static(path.resolve(__dirname, 'public')))//body
app.use(bodyParser());//midware auth
app.use(verifyToken);// api
app.use(router.routes()).use(router.allowedMethods())// assets
app.use(assets.routes()).use(assets.allowedMethods())// 404
app.use(async (ctx, next) => {await next()if (ctx.status === 404) {await sendfile(ctx, path.resolve(__dirname, 'public/index.html'))}
})app.listen(3000, () => {console.log(`> http://127.0.0.1:3000`)
})
前端请求(登录+打开主页)
import { useState, useEffect } from 'react'
import getTokenFromCookie from './tools'
function App() {const [response, setResponse] = useState({})const token = getTokenFromCookie();useEffect(() => {fetch('/api/login', {method: 'post',headers: {'Content-Type': 'application/json','Authorization': `Bearer ${token}`,},body: JSON.stringify({username: 'Tom',password: 123456})}).then(res => res.json()).then(res => {setResponse(res);})// fetch('/api/home', {// method: 'post',// headers: {// 'Content-Type': 'application/json',// 'Authorization': `Bearer ${token}`,// },// body: JSON.stringify({// username: 'Tom',// password: 123456// })// })// .then(res => res.json())// .then(res => {// setResponse(res);// })}, [])const { nickname, icon, msg } = response || {}return (<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>{nickname ? <div><h1>icon: {icon}</h1><h1>nickname: {nickname}</h1><h1>msg: {msg}</h1></div>: <h1>msg: {msg}</h1>}</div>)
}export default App相关文章:
react+koa+vite前后端模拟jwt鉴权过程
路由组件(生成token) const Router require(koa/router) const jwt require(jsonwebtoken); const router new Router()const mockDbUserInfo [{nickname: xxxliu,username: Tom,password: 123456,icon: url1},{nickname: xxx,username: John,passw…...
VK1616是LED显示控制驱动电路/LED驱动IC、数显驱动芯片、数码管驱动芯片
产品品牌:永嘉微电/VINKA 产品型号:VK1616 封装形式:SOP16 产品年份:新年份 概述:VK1616是一种数码管或点阵LED驱动控制专用芯片,内部集成有3线串行接口、数据锁存器、LED 驱动等电路。SEG脚接LED阳极&a…...
开箱报告,Simulink Toolbox库模块使用指南(五)——S-Fuction模块(C MEX S-Function)
文章目录 前言 C MEX S-Function 算法原理 原始信号创建 编写S函数 仿真验证 Tips 分析和应用 总结 前言 见《开箱报告,Simulink Toolbox库模块使用指南(一)——powergui模块》 见《开箱报告,Simulink Toolbox库模块使用…...
摄像头的调用和视频识别
CV_tutorial3 摄像头调用实时播放保存视频 运动目标识别帧差法背景减除法 摄像头调用 创建视频捕捉对象:cv2.VideoCapture() 参数为视频设备的索引号,就一个摄像投的话写0默认; 或者是指定要读取视频的路径。 实时播放 import cv2 import …...
多通道分离与合并
目录 1.多通道分离split() 2.多通道合并merge() 3.Android JNI demo 1.多通道分离split() void cv::split ( InputArray m, OutputArrayOfArrays mv ) m:待分离的多通道图像。 mv:分离后的单通道图像,为向量vector形式。 2.多通道合并merge…...
JOJO的奇妙冒险
JOJO,我不想再做人了。 推荐一部动漫 JOJO的奇妙冒险 荒木飞吕彦创作的漫画 《JOJO的奇妙冒险》是由日本漫画家荒木飞吕彦所著漫画。漫画于1987年至2004年在集英社的少年漫画杂志少年JUMP上连载(1987年12号刊-2004年47号刊),2005年后在集英…...
LeetCode56.合并区间
这道题我想了一会儿,实在想不到比较好的算法,只能硬着头皮写了,然后不断的debug,经过我不懈的努力,最后还是AC,不过效率确实低。 我就是按照最直接的方法来,先把intervals数组按照第一个数star…...
【内推码:NTAMW6c】 MAXIEYE智驾科技2024校招启动啦
MAXIEYE智驾科技2024校招启动啦【内推码:NTAMW6c】 【招聘岗位超多!!公司食堂好吃!!】 算法类:感知算法工程师、SLAM算法工程师、规划控制算法工程师、目标及控制算法工程师、后处理算法工程师 软件类&a…...
Python框架【模板继承 、继承模板实战、类视图 、类视图的好处 、类视图使用场景、基于调度方法的类视图】(四)
👏作者简介:大家好,我是爱敲代码的小王,CSDN博客博主,Python小白 📕系列专栏:python入门到实战、Python爬虫开发、Python办公自动化、Python数据分析、Python前后端开发 📧如果文章知识点有错误…...
对于前端模块化的理解与总结(很全乎)
目录 模块化的好处 模块化的commonJS导入导出 暴露(导出)模块:module.exports value或exports.xxx value 导入模块——使用 es6模块化 方法一逐个导出 方法二默认导出 方法三 方法四 方法五 export 和import 同时存在 多个文件导出到一个文件后在相关文件…...
NewStarCTF 2022 web方向题解 wp
----------WEEK1---------- BUU NewStarCTF 公开赛赛道 WEEK1 [NotPHP] 先看题目,要传参加绕过。 分析一下代码:首先get一个datadata://test/plain,Wel…。然后key1和2用数组可以绕过。num2077a可以绕过弱类型。eval()中的php语句被#注释了,…...
WebGL矩阵变换库
目录 矩阵变换库: Matrix4对象所支持的方法和属性如表所示: 方法属性规范: 虽然平移、旋转、缩放等变换操作都可以用一个44的矩阵表示,但是在写WebGL程序的时候,手动计算每个矩阵很耗费时间。为了简化编程…...
block层:8. deadline调度器
deadline 源码基于5.10 0. 私有数据 struct deadline_data {/** run time data*//** requests (deadline_rq s) are present on both sort_list and fifo_list*/struct rb_root sort_list[2];struct list_head fifo_list[2];/** next in sort order. read, write or both ar…...
DTO,VO,PO的意义与他们之间的转换
DTO(Data Transfer Object):数据传输对象,这个概念来源于J2EE的设计模式,原来的目的是为了EJB的分布式应用提供粗粒度的数据实体,以减少分布式调用的次数,从而提高分布式调用的性能和降低网络负…...
Java 集合框架2
一、关于set接口的常用类 1.HashSet类 用来处理无序的单列数据,没有重复的元素,重复的元素算一个 i.构造方法 //HashSet类是set接口的子类,是无序的单列数据,没有重复的元素,重复的元素算一个 //HashSet的构造方法 //HashSet() …...
2024王道408数据结构P144 T16
2024王道408数据结构P144 T16 思考过程 首先看题目,要求我们把二叉树的叶子结点求出来并且用链表的方式存储,链接时用叶结点的右指针来存放单链表指针。我们很清楚可以看出来能用中序遍历递归的方式实现,因为第一个叶子结点在整棵树的最左下…...
【ARM Coresight 系列文章 22 -- linux frace 与 trace-cmd】
文章目录 ftrace 介绍trace-cmd 介绍trace-cmd 常用跟踪事件ftrace 与 trace-cmd 关系ftrace 编译依赖 ftrace 介绍 ftrace 是 Linux 内核中的一个跟踪工具,主要用于帮助开发者分析和调试内核的行为。ftrace 的名字来源于 “function tracer”,它最初是…...
MyBatis的一级缓存和二级缓存是怎么样的?
目录 1. 一级缓存 2. 一级缓存失效的几种情况 3. 二级缓存 4.二级缓存失效的情况 5. 二级缓存的相关配置 6. 缓存的查询顺序 MyBatis 的缓存共分为一级缓存和二级缓存。 1. 一级缓存 一级缓存是 SqlSession 级别的,通过同一个 SqlSession 查询到的数据会被缓…...
下载的文件被Windows 11 安全中心自动删除
今天从CSDN上下载了自己曾经上传的文件,但是浏览器下载完之后文件被Windows安全中心自动删除,说是带病毒。实际是没有病毒的,再说了即便有病毒也不应该直接删除啊,至少给用户一个保留或删除的选项。 研究了一番,可以暂…...
【Java List与数组】List<T>数组和数组List<T>的区别(124)
List数组:存储List的数组,即:数组中的元素是:List; 数组List:存储数组的List,即:List中的数据是类型的数组; 测试案例: import java.util.ArrayList; impor…...
如何快速解锁网易云音乐NCM格式:免费无损转换完整指南
如何快速解锁网易云音乐NCM格式:免费无损转换完整指南 【免费下载链接】ncmdump ncmdump - 网易云音乐NCM转换 项目地址: https://gitcode.com/gh_mirrors/ncmdu/ncmdump 你是否曾经从网易云音乐下载了喜爱的歌曲,却发现这些NCM格式文件无法在其他…...
Win11Debloat:3步让你的Windows 11系统重获新生
Win11Debloat:3步让你的Windows 11系统重获新生 【免费下载链接】Win11Debloat 一个简单的PowerShell脚本,用于从Windows中移除预装的无用软件,禁用遥测,从Windows搜索中移除Bing,以及执行各种其他更改以简化和改善你的…...
无网环境下的containerd部署实战:从静态二进制到服务就绪
1. 为什么需要离线部署containerd? 在工业控制、军工系统、金融核心业务等特殊场景中,服务器往往运行在物理隔离的网络环境中。我曾经参与过一个智能制造项目,生产线的控制服务器连内网都不允许接入,更别说访问互联网了。这种环境…...
终极指南:如何用VideoDownloadHelper快速下载网页视频
终极指南:如何用VideoDownloadHelper快速下载网页视频 【免费下载链接】VideoDownloadHelper Chrome Extension to Help Download Video for Some Video Sites. 项目地址: https://gitcode.com/gh_mirrors/vi/VideoDownloadHelper 还在为无法保存网页视频而烦…...
Linux新手必看:Deepin、Mint、Fedora等主流发行版安装镜像获取全攻略
Linux新手必看:Deepin、Mint、Fedora等主流发行版安装镜像获取全攻略 当你第一次踏入Linux世界的大门,面对众多发行版的选择,获取正确的安装镜像往往是第一步。就像选择一把合适的钥匙,镜像的质量和来源直接关系到系统安装的成败。…...
移动开发终极指南:如何利用stb库在Android和iOS平台实现高性能图像处理
移动开发终极指南:如何利用stb库在Android和iOS平台实现高性能图像处理 【免费下载链接】stb stb single-file public domain libraries for C/C 项目地址: https://gitcode.com/GitHub_Trending/st/stb 在移动应用开发中,图像处理是提升用户体验…...
springboot-vue基于web框架的高校教材征订管理系统的设计与实现
目录技术选型与架构设计核心功能模块划分数据库设计要点开发阶段规划关键技术实现方案部署与运维方案项目技术支持源码获取详细视频演示 :文章底部获取博主联系方式!同行可合作技术选型与架构设计 后端技术栈 采用Spring Boot作为核心框架,整…...
SillyTavern角色创建完全指南:从入门到精通
SillyTavern角色创建完全指南:从入门到精通 【免费下载链接】SillyTavern LLM Frontend for Power Users. 项目地址: https://gitcode.com/GitHub_Trending/si/SillyTavern 一、基础认知:揭开角色系统的面纱 1.1 什么是角色系统? 想…...
VSCode 高效开发:配置 Pixel Dream Workshop 模型调用的代码片段与插件
VSCode 高效开发:配置 Pixel Dream Workshop 模型调用的代码片段与插件 1. 为什么需要优化开发工作流 如果你经常使用Pixel Dream Workshop这类AI模型进行开发,可能会遇到一个共同痛点:每次调用API时都要重复编写相似的请求代码,…...
运动控制选EtherCAT,过程控制用PROFINET?深入聊聊工业以太网协议背后的设计哲学与取舍
工业以太网协议的设计哲学:EtherCAT与PROFINET的技术抉择 在自动化生产线上,一个机械臂需要以0.1毫米的精度重复定位,而百米外的反应釜温度必须控制在0.5℃范围内——这两种看似相似的工业控制需求,背后却对应着完全不同的通信协议…...
