node.js实现分页,jwt鉴权机制,token,cookie和session的区别
文章目录
- 1. 分⻚功能
- 2. jwt鉴权机制
- 1.jwt是什么
- 2.jwt的应用
- 3.优缺点
- 3. cookie,token,session的对比
1. 分⻚功能
- 为什么要分页
- 如果数据量很⼤,⽐如⼏万条数据,放在⼀个⻚⾯显⽰的话显然不友好,这时候就需要采⽤分⻚显⽰的形式。
- 如每次只显⽰10条数据要实现分⻚功能,实际上就是从结果集中显⽰第1(10条记录作为第1⻚,显⽰第11)20条记录作为第2⻚,以此类推。
- 分⻚实际上就是从结果集中截取出第M~N条记录
- 实现
- 前端实现分⻚功能,需要后端返回必要的数据,如总的⻚数,总的数据量,当前⻚,当前的数据
- 后端的处理逻辑
- 获取⽤⼾参数⻚码数page和每⻚显⽰的数⽬pageSize,其中page是必须传递的参数,pageSize为可选参数,默认为10
- 编写SQL语句,利⽤limit和offset关键字进⾏分⻚查询
- 查询数据库,返回总数据量、总⻚数、当前⻚、当前⻚数据给前端
var mysql = require('mysql'); var connection = mysql.createConnection({host : 'localhost',user : 'root',password : '1q2w3e4r',database : 'test' }); connection.connect(); let param = {pageSize: 20,pageNo: 1 } let pageSize = param.pageSize || 10; let start = (param.pageNo - 1) * pageSize; // 每⼀条数据的起始位置start let sql = `select * from students order by score desc limit ${pageSize} OFFSET ${start}` connection.query(sql, function (error, results, fields) {if (error) throw error;console.log(results); }); connection.end();
⾸先确定每⻚显⽰的数量pageSize,当前⻚的索引pageIndex (从1开始),确定LIMIT 和OFFSET 应该设定的值:- LIMIT 总是设定为pageSize
- OFFSET计算公式为pageSize*(pageIndex-1)
确定了这两个值,就能查询出第N⻚的数
2. jwt鉴权机制
1.jwt是什么
JWT(JSONWebToken),本质就是⼀个字符串书写规范,作⽤是⽤来在⽤⼾和服务器之间传递安全可靠的信息。
- JSON Web Tokens 的组成
在其紧凑的格式中,JSON Web Tokens 由三部分组成,由点 (.)分隔,它们是:Header(标头)Payload(有效载荷 ) Signature(签名)- Header
标头通常由两部分组成:令牌的类型,即 JWT,以及所使用的签名算法,例如 HMAC SHA256 或 RSA.
有效示例{ "alg": "HS256", "typ": "JWT" }
- Payload
令牌的第二部分是有效负载,其中包含声明。声明是关于实体(通常是用户)和附加数据的声明。声明分为三种类型:registered(注册声明)、public(公共声明)和private(私人声明).- 已注册声明: 这些是一组预定义的声明,它们不是强制性的,但建议使用,以提供一组有用的、可互操作的声明。其中一些是:
iss(发布者)、
exp(到期时间)、
sub(主题)、
aud(受众)
nbf: 定义在什么时间之前,该jwt都是不可用的.
iat: jwt的签发时间
jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。. - 公共声明: 这些可以由使用 JWT 的人随意定义。但是为了避免冲突,它们应该在IANA JSON Web Token注册表中定义,或者定义为包含抗冲突名称空间的 URI。
- 私人声明: 这些是为在同意使用它们的各方之间共享信息而创建的自定义声明,既不是注册声明也不是公共声明
有效载荷示例{ "sub": "1234567890", "name": "John Doe", "admin": true }
- 已注册声明: 这些是一组预定义的声明,它们不是强制性的,但建议使用,以提供一组有用的、可互操作的声明。其中一些是:
- Signature
要创建签名部分,您必须采用编码标头、编码有效负载、秘码、标头中指定的算法,然后对其进行签名.
- Header
2.jwt的应用
- 安装指令
npm install jsonwebtoken
- 加密
参数解析jwt.sign(payload, secretOrPrivateKey, [options, callback])
-
payload:可以是表示有效 JSON 的对象文本、缓冲区或字符串
-
secretOrPrivateKey:是一个字符串(utf-8 编码)、缓冲区、对象或 KeyObject,其中包含 HMAC 算法或 PEM 的密钥 RSA 和 ECDSA 的编码私钥
-
options:
- algorithm(默认:HS256)
- expiresIn:以秒为单位或描述时间跨度 Vercel/ms 的字符串 (60, “2 days”, “10h”, “7d”)。
- notBefore:以秒为单位或描述时间跨度 Vercel/ms 的字符串。
- mutatePayload:如果为 true,则 sign 函数将直接修改 payload 对象。如果您在将声明应用于有效负载之后但在将其编码为令牌之前需要对有效负载的原始引用,这将非常有用。
- allowInsecureKeySizes:如果为 true,则允许将模数低于 2048 的私钥用于 RSA
- allowInvalidAsymmetricKeyTypes:如果为 true,则允许与指定算法不匹配的非对称键。此选项仅用于向后兼容,应避免使用。
var jwt = require('jsonwebtoken');const secret = 'xixi' // 私钥var token = jwt.sign({ name: '西西' }, secret);console.log(token, '1111')var token1 = jwt.sign({ name: '西西' }, secret, { algorithm: 'HS512' });console.log(token1, '2222')// 异步jwt.sign({ name: '西西' }, secret, { algorithm: 'HS512' }, function(err, token) {console.log(token, '3333');});var older_token = jwt.sign({ name: '西西', iat: Math.floor(Date.now() / 1000) - 30 }, secret);console.log(older_token, '4444');
加密时效性var jwt = require('jsonwebtoken');const secret = 'xixi' // 私钥let token = jwt.sign({exp: Math.floor(Date.now() / 1000) + (60 * 60),name: '西西'}, secret);console.log(token, '1111')let token1 = jwt.sign({name: '西西'}, secret, { expiresIn: 60 * 60 });console.log(token1, '2222')let tokenh = jwt.sign({name: '西西'}, secret, { expiresIn: '1h' });console.log(tokenh, '3333')
-
- 解密
参数解析jwt.verify(token, secretOrPublicKey, [options, callback])
- token是 JsonWebToken 字符串
- secretOrPublicKey是一个字符串(utf-8 编码)、缓冲区或 KeyObject,其中包含 HMAC 算法的密钥或 PEM RSA 和 ECDSA 的编码公钥。
- options
- algorithms:包含允许算法名称的字符串列表。例如。[“HS256”, “HS384”]
- audience:如果要检查 audience (),请在此处提供一个值。可以根据字符串、正则表达式或字符串和/或正则表达式列表检查受众。
- complete:返回具有 decoded 的对象,而不仅仅是有效负载的通常内容。{ payload, header, signature }
- issuer(可选):字段有效值的字符串或字符串数组。iss
- jwtid(可选):如果要检查 JWT ID (),请在此处提供字符串值。jti
- ignoreExpiration:如果不验证令牌的过期时间。true
- ignoreNotBefore…
- subject:如果要检查主题 (),请在此处提供一个值sub
- clockTolerance:检查 and 声明时可容忍的秒数,以处理不同服务器之间的小时钟差异nbfexp
- maxAge:令牌仍然有效的最大允许年龄。它以秒或描述时间跨度 vercel/ms 的字符串表示。
- clockTimestamp:应用作所有必要比较的当前时间(以秒为单位)。
- nonce:如果要检查 Claim,请在此处提供 String 值。它用于 ID 令牌的 Open ID。(Open ID 实施说明nonce)
- allowInvalidAsymmetricKeyTypes:如果为 true,则允许与指定算法不匹配的非对称键。此选项仅用于向后兼容,应避免使用。
let token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoi6KW_6KW_IiwiaWF0IjoxNzMzMjEwMTc5fQ.24KOMgCK2W6DTUvcotDlP2ciKL_EmA9tTdGJLMZByfc' var decoded = jwt.verify(token, secret); console.log(decoded) // bar let token1 = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoi6KW_6KW_IiwiaWF0IjoxNzMzMjEyMDQ4LCJleHAiOjE3MzMyMTU2NDh9.3gDiIfvDNWbn1DR5a0pZtr0Cwkv_aueHZgui8HVluRo' var decoded1 = jwt.verify(token1, secret); console.log(decoded1)
- 校验
使⽤koa-jwt 中间件进⾏验证,⽅式⽐较简单- 安装指令
npm install koa-jwt
- 安装指令
app.use(koajwt({secret: 'test_token' }).unless({ // 配置白名单path: [/\/api\/register/, /\/api\/login/]
- 案例
// 服务代码 const Koa = require('koa') const app = new Koa() var jwt = require('jsonwebtoken'); const Router = require('koa-router') var router = new Router(); // 总路由 const koajwt = require('koa-jwt'); const cors = require('koa2-cors') const secret = 'xixi' // 私钥 // 解决跨域 app.use(cors({origin: function(ctx) {// 这里可以根据实际需求设置允许跨域的域名,或者使用函数进行复杂配置// if (ctx.url === '/crossdomain') {// return 'http://example.com';// }return '*'; // 允许所有域},maxAge: 5, // 表示在5秒内不需要再发送预检请求credentials: true, // 允许cookiesallowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],allowHeaders: ['Content-Type', 'Authorization', 'Accept'], })) // 可以通过unless配置接⼝⽩名单,也就是哪些URL可以不⽤经过校验,像登陆/注册都可以不⽤校验 // 校验的中间件需要放在需要校验的路由前⾯,⽆法对前⾯的URL进⾏校验 app.use(koajwt({secret}))router.post('/api/login_post_json', async (ctx) => {console.log(ctx.request)console.log('abcd');ctx.body = "abcd页"; })app.use(router.routes()).use(router.allowedMethods()); app.listen(8081, function() {console.log('服务启动!端口号:8081') });
// html 代码 <!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><script src="https://cdn.staticfile.org/jquery/3.4.1/jquery.min.js"></script></head><body><button id="btnPOST">POST</button><script>$(function () {// 2. 测试POST接口let token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoi6KW_6KW_IiwiaWF0IjoxNzMzMjg5ODE3fQ.rlwgJqUEFXO4_K7FijNELqkOLnOBgGzx1GCn7QY4rXU'$('#btnPOST').on('click', function () {$.ajax({type: 'POST',url: 'http://127.0.0.1:8081/api/login_post_json',headers: {'Content-Type': 'application/json;charset=utf-8', Authorization: `Bearer ${token}` }, // 注:需要在请求头中使用Authorization字段并使用Bearer模式来发送token,data: { name: '西西', author: '11111'},success: function (res) {console.log(res)},})})})</script></body> </html>
- 安装指令
3.优缺点
优点:
- json具有通⽤性,所以可以跨语⾔
- 组成简单,字节占⽤⼩,便于传输
- 服务端⽆需保存会话信息,很容易进⾏⽔平扩展
- ⼀处⽣成,多处使⽤,可以在分布式系统中,解决单点登录问题
- 可防护CSRF攻击
缺点:
- payload部分仅仅是进⾏简单编码,所以只能⽤于存储逻辑必需的⾮敏感信息
- 需要保护好加密密钥,⼀旦泄露后果不堪设想
- 为避免token被劫持,最好使⽤https协议
3. cookie,token,session的对比
Cookie、Token和Session是Web开发中常用的三种用户会话管理机制
-
Cookie
Cookie 是一种由服务器发送到客户端浏览器的小数据片段,用于存储用户的状态信息。
它主要用于跟踪用户会话、存储用户偏好设置、记住用户登录状态等。
优点- 存储在客户端,服务器负担较轻。
- 每次请求时自动发送,适合无状态应用。
缺点
- 容量有限,单个Cookie的大小通常不超过4KB。
- 安全性较低,容易被篡改或遭受跨站请求伪造(CSRF)攻击
-
Token
Token是服务端生成的一串字符串,用作客户端进行请求的令牌。当用户第一次登录后,服务器生成一个Token并将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。
优点- 无状态,适合无状态和分布式系统。
- 安全性较高,因为Token通常经过加密处理。
缺点
- 每次请求都需要验证Token,可能会增加服务器的计算负担
-
Session
Session是在服务器端存储用户会话信息的机制。当用户访问网站时,服务器会为该用户创建一个唯一的Session,并生成一个Session ID。这个Session ID用于在多个请求之间保持用户的会话状态。
优点- 存储在服务器端,安全性较高,因为数据不存储在客户端。
- 可以存储大量数据,没有容量限制。
缺点
- 占用服务器资源,可能影响性能
特性 | Cookie | Session | Token |
---|---|---|---|
存储位置 | 客户端存储 | 服务器端存储,客户端存储 Session ID | 客户端存储 |
安全性 | 易受 CSRF 攻击,易被篡改 | 更安全,敏感数据存储在服务器端 | 一旦泄露可能被盗用 |
容量 | 4KB 限制 | 服务器端可以存储更多数据 | 受限于 Token 大小,但一般较小 |
性能 | 自动随请求发送 | 服务器需要维护状态,增加负担 | 无状态机制,适合分布式应用 |
使用场景 | 适合简单的用户状态管理 | 适合需要存储大量用户数据的应用 | 适合需要无状态认证和分布式系统的应用 |
相关文章:

node.js实现分页,jwt鉴权机制,token,cookie和session的区别
文章目录 1. 分⻚功能2. jwt鉴权机制1.jwt是什么2.jwt的应用3.优缺点 3. cookie,token,session的对比 1. 分⻚功能 为什么要分页 如果数据量很⼤,⽐如⼏万条数据,放在⼀个⻚⾯显⽰的话显然不友好,这时候就需要采⽤分⻚…...

34 基于单片机的指纹打卡系统
目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于STC89C52RC,采用两个按键替代指纹,一个按键按下,LCD12864显示比对成功,则 采用ULN2003驱动步进电机转动,表示开门,另一个…...
【Linux】用户操作命令
声明:以下内容均学习自《Linux就该这么学》一书 1、管理员root Linux系统的管理员之所以是root,并不是因为它的名字叫root,而是因为该用户的身份号码UID(User IDentification)的数值是0。UID相当于身份证号码&#x…...

Y20030018基于Java+Springboot+mysql+jsp+layui的家政服务系统的设计与实现 源代码 文档
家政服务系统的设计与实现 1.摘要2.开发目的和意义3.系统功能设计4.系统界面截图5.源码获取 1.摘要 随着人们生活水平的提高,老龄化、少子化等多重因素影响,我国对家政服务人群的需求与日俱增。家政服务行业对我国的就业和社会效益贡献也与日俱增&#…...

windows部署PaddleSpeech详细教程
windows安装paddlespeech步骤: 1. 安装vs c编译环境 对于 Windows 系统,需要安装 Visual Studio 来完成 C 编译环境的安装。 Microsoft C Build Tools - Visual Studio 2. 安装conda conda create -y -p paddlespeech python3.8 conda activate pad…...

线程条件变量 生产者消费者模型 Linux环境 C语言实现
只能用来解决同步问题,且不能独立使用,必须配合互斥锁一起用 头文件:#include <pthread.h> 类型:pthread_cond_t PTHREAD_COND_INITIALIZER 初始化 初始化:int pthread_cond_init(pthread_cond_t * cond, NULL);…...

C++ packaged_task
packaged_task 是 C11 标准库中引入的一个模板类,它用于将可调用对象(如函数、lambda 表达式、函数对象或绑定表达式)包装起来,并允许异步地获取其结果packaged_task 类提供了一种方便的方式来创建任务,这些任务可以被…...

【联表查询】.NET开源 ORM 框架 SqlSugar 系列
.NET开源 ORM 框架 SqlSugar 系列 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列【Code First】.NET开源 ORM 框架 SqlSugar 系列【数据事务…...

嵌入式C编程:宏定义与typedef的深入对比与应用
目录 一、宏定义(Macro Definition) 1.1. 特点与应用 1.1.1 定义常量 1.1.2 定义函数式宏 1.1.3 条件编译 1.2. 作用范围和生命周期方面 1.3. 应用注意事项 二、typedef 2.1. 特点与应用 2.1.1 简化类型声明 2.1.2 提高代码可读性 2.1.3 实现…...
高级java每日一道面试题-2024年12月03日-JVM篇-什么是Stop The World? 什么是OopMap? 什么是安全点?
如果有遗漏,评论区告诉我进行补充 面试官: 什么是Stop The World? 什么是OopMap? 什么是安全点? 我回答: 在Java虚拟机(JVM)中,Stop The World、OopMap 和 安全点 是与垃圾回收(GC)和性能优化密切相关的概念。理…...
【openGauss︱PostgreSQL】openGauss或PostgreSQL查表、索引、序列、权限、函数
【openGauss︱PostgreSQL】openGauss或PostgreSQL查表、索引、序列、权限、函数 一、openGauss查表二、openGauss查索引三、openGauss查序列四、openGauss查权限五、openGauss或PostgreSQL查函数六、PostgreSQL查表七、PostgreSQL查索引八、PostgreSQL查序列九、PostgreSQL查权…...

Dataset用load_dataset读图片和对应的caption的一个坑
代码: data_files {} if args.train_data_dir is not None:data_files["train"] os.path.join(args.train_data_dir, "**")dataset load_dataset("imagefolder",data_filesdata_files,cache_dirargs.cache_dir,) 数据࿱…...
【信息系统项目管理师】第7章:项目立项管理 考点梳理
文章目录 7.1 项目建议与立项申请7.2 项目可行性研究7.2.1 可行性研究的内容7.2.2 初步可行性研究7.2.3 详细可行性研究(重点) 7.3 项目评估与决策 【学习建议】本章大概考选择题2分左右,有可能考案例题。论文早年考过。本章知识点比较集中&a…...
知识库、提示词对大语言模型的影响测试
简介 通过对比有无知识库,测试大语言模型的回答 有无提示词对比测试 前提 大语言模型:Qwen1.5-1.8B-Chat-GPTQ-Int4 GPU:1650super,显存4G 提问:华为mate70 没有提示词 回答的内容如下 “华为mate70pro和mate40p…...
vistat-监控和分析网络状态
vistat 是一个用于监控和分析网络状态的工具,通常用于查看网络接口、流量、连接等实时数据。 原理:用户态调用系统接口获取内核中的网络统计信息。 核心功能:网络接口流量监控、查看连接状态、带宽使用分析。 使用方法: 查看接…...

EasyAnimateV5 视频生成大模型原理详解与模型使用
在数字内容创作中,视频扮演的角色日益重要。然而,创作高质量视频通常耗时且昂贵。EasyAnimate 系列旨在利用人工智能技术简化这一过程。EasyAnimateV5 建立在其前代版本的基础之上,不仅在质量上有所提升,还在多模态数据处理和跨语…...

水稻和拟南芥生命周期中单碱基分辨率的m6A定量分析-文献精读88
Quantitative profiling of m6A at single base resolution across the life cycle of rice and Arabidopsis 水稻和拟南芥生命周期中单碱基分辨率的m6A定量分析 水稻参考基因组(日本晴品种)-CSDN博客 “Xian”(籼)和“Geng”&…...

学习threejs,使用canvas更新纹理
👨⚕️ 主页: gis分享者 👨⚕️ 感谢各位大佬 点赞👍 收藏⭐ 留言📝 加关注✅! 👨⚕️ 收录于专栏:threejs gis工程师 文章目录 一、🍀前言1.1 ☘️Texture 贴图 二、…...

【笔记2-3】ESP32 bug:PSRAM chip not found or not supported 没有外部PSRAM问题解决
主要参考b站宸芯IOT老师的视频,记录自己的笔记,老师讲的主要是linux环境,但配置过程实在太多问题,就直接用windows环境了,老师也有讲一些windows的操作,只要代码会写,操作都还好,开发…...

大数据hadoop、spark、flink、kafka发展的过程
将sql 代发翻译成java 程序 将python 程序通过pyspark框架翻译成java 程序,然后运行在spark计算框架上...

AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...

基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...

HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...

PL0语法,分析器实现!
简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果
题目描述 一个具有 n 个顶点e条边的无向图,该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序,确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数,分别表示n 和 e 的值(1…...

基于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…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...