node.js实现分页,jwt鉴权机制,token,cookie和session的区别

文章目录

  • 1. 分⻚功能
  • 2. jwt鉴权机制
    • 1.jwt是什么
    • 2.jwt的应用
    • 3.优缺点
  • 3. cookie,token,session的对比


1. 分⻚功能

  1. 为什么要分页
    • 如果数据量很⼤,⽐如⼏万条数据,放在⼀个⻚⾯显⽰的话显然不友好,这时候就需要采⽤分⻚显⽰的形式。
    • 如每次只显⽰10条数据要实现分⻚功能,实际上就是从结果集中显⽰第1(10条记录作为第1⻚,显⽰第11)20条记录作为第2⻚,以此类推。
    • 分⻚实际上就是从结果集中截取出第M~N条记录
  2. 实现
    • 前端实现分⻚功能,需要后端返回必要的数据,如总的⻚数,总的数据量,当前⻚,当前的数据
    • 后端的处理逻辑
    1. 获取⽤⼾参数⻚码数page和每⻚显⽰的数⽬pageSize,其中page是必须传递的参数,pageSize为可选参数,默认为10
    2. 编写SQL语句,利⽤limit和offset关键字进⾏分⻚查询
    3. 查询数据库,返回总数据量、总⻚数、当前⻚、当前⻚数据给前端
    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(签名)
    1. Header
      标头通常由两部分组成:令牌的类型,即 JWT,以及所使用的签名算法,例如 HMAC SHA256 或 RSA.
      有效示例{ "alg": "HS256", "typ": "JWT" }
    2. 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 }
    3. Signature
      要创建签名部分,您必须采用编码标头、编码有效负载、秘码、标头中指定的算法,然后对其进行签名.

2.jwt的应用

  1. 安装指令
    npm install jsonwebtoken
    
  2. 加密
    jwt.sign(payload, secretOrPrivateKey, [options, callback]
    参数解析
    1. payload:可以是表示有效 JSON 的对象文本、缓冲区或字符串

    2. secretOrPrivateKey:是一个字符串(utf-8 编码)、缓冲区、对象或 KeyObject,其中包含 HMAC 算法或 PEM 的密钥 RSA 和 ECDSA 的编码私钥

    3. 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')
      

      在这里插入图片描述

  3. 解密
    jwt.verify(token, secretOrPublicKey, [options, callback])
    
    参数解析
    1. token是 JsonWebToken 字符串
    2. secretOrPublicKey是一个字符串(utf-8 编码)、缓冲区或 KeyObject,其中包含 HMAC 算法的密钥或 PEM RSA 和 ECDSA 的编码公钥。
    3. 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)
    
    在这里插入图片描述
  4. 校验
    使⽤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, // 允许cookies
        allowMethods: ['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 是一种由服务器发送到客户端浏览器的小数据片段,用于存储用户的状态信息。
    它主要用于跟踪用户会话、存储用户偏好设置、记住用户登录状态等。
    优点

    1. 存储在客户端,服务器负担较轻‌。
    2. ‌每次请求时自动发送‌,适合无状态应用。

    缺点

    1. 容量有限‌,单个Cookie的大小通常不超过4KB。
    2. 安全性较低‌,容易被篡改或遭受跨站请求伪造(CSRF)攻击‌
  • Token
    Token是服务端生成的一串字符串,用作客户端进行请求的令牌‌。当用户第一次登录后,服务器生成一个Token并将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。
    优点

    1. 无状态‌,适合无状态和分布式系统。
    2. 安全性较高‌,因为Token通常经过加密处理。

    缺点

    1. 每次请求都需要验证Token‌,可能会增加服务器的计算负担‌
  • Session
    ‌Session是在服务器端存储用户会话信息的机制‌。当用户访问网站时,服务器会为该用户创建一个唯一的Session,并生成一个Session ID。这个Session ID用于在多个请求之间保持用户的会话状态。
    优点

    1. 存储在服务器端,安全性较高‌,因为数据不存储在客户端。
    2. 可以存储大量数据‌,没有容量限制。

    缺点

    1. 占用服务器资源‌,可能影响性能‌
特性CookieSessionToken
存储位置客户端存储服务器端存储,客户端存储 Session ID客户端存储
安全性易受 CSRF 攻击,易被篡改更安全,敏感数据存储在服务器端一旦泄露可能被盗用
容量4KB 限制服务器端可以存储更多数据受限于 Token 大小,但一般较小
性能自动随请求发送服务器需要维护状态,增加负担无状态机制,适合分布式应用
使用场景适合简单的用户状态管理适合需要存储大量用户数据的应用适合需要无状态认证和分布式系统的应用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/928904.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

消息中间件-Kafka2-3.9.0源码构建

消息中间件-Kafka2-3.9.0源码构建 1、软件环境 JDK Version 1.8Scala Version 2.12.0Kafka-3.9.0 源码包 下载地址&#xff1a;https://downloads.apache.org/kafka/3.9.0/kafka-3.9.0-src.tgzGradle Version > 8.8Apache Zookeeper 3.7.0 2、源码编译 打开源码根目录修改…

修复docker启动失败:Failed to start Docker Application Container Engine

配置了镜像源之后&#xff0c;运行sudo systemctl restart docker.service失败&#xff0c;提示让运行systemctl status docker.service或journalctl -xeu docker.service查看详细信息。 运行后者发现有如下日志&#xff1a; 红色区域是我设置的一个镜像源这个日志的意思就是…

【英特尔IA-32架构软件开发者开发手册第3卷:系统编程指南】2001年版翻译,2-43

文件下载与邀请翻译者 学习英特尔开发手册&#xff0c;最好手里这个手册文件。原版是PDF文件。点击下方链接了解下载方法。 讲解下载英特尔开发手册的文章 翻译英特尔开发手册&#xff0c;会是一件耗时费力的工作。如果有愿意和我一起来做这件事的&#xff0c;那么&#xff…

遗传算法与深度学习实战(26)——编码卷积神经网络架构

遗传算法与深度学习实战&#xff08;26&#xff09;——编码卷积神经网络架构 0. 前言1. EvoCNN 原理1.1 工作原理1.2 基因编码 2. 编码卷积神经网络架构小结系列链接 0. 前言 我们已经学习了如何构建卷积神经网络 (Convolutional Neural Network, CNN)&#xff0c;在本节中&a…

react 路由鉴权

权限路由一般两种 1中接口中返回菜单 2 接口中返回权限&#xff0c;前端做匹配 一般都是那种结合&#xff0c;react中没有vue那种钩子函数如何做&#xff1f; 在项目中写一个高阶函数&#xff0c;在高阶函数中判断权限、是否登录等操作app.tsx或者man.tsx中使用 《AuthRouter》…

Ansys Maxwell:电机中的磁芯和磁体损耗

了解磁体中的涡流损耗和电动机叠片中的磁芯损耗 磁体中的涡流损耗会影响电动机的效率和热性能。当交变磁场在导电材料&#xff08;例如电动机中使用的磁铁&#xff09;内感应出电流回路时&#xff0c;就会发生这种现象。这些电流会产生热量&#xff0c;导致效率降低和磁热点。…

EtherCAT转ProfiNet网关实现西门子1200PLC与伺服电机连接的通讯案例

一. 案例背景 西门子1200PLC通过捷米特JM-ECTM-PN(EtherCAT转ProfiNet)网关将松下伺服电机(包括不限于型号MHMFO22D1U2M)或EtherCAT协议的其它设备或连接到ProfiNetPLC上&#xff0c;并在正常运行中支持EtherCAT协议。本产品可作为EtherCAT主站&#xff0c;做为西门子S7-1200系…

在 MacOS 上为 LM Studio 更换镜像源

在 MacOS 之中使用 LM Studio 部署本地 LLM时&#xff0c;用户可能会遇到无法下载模型的问题。 一般的解决方法是在 huggingface.co 或者国内的镜像站 hf-mirror.com 的项目介绍卡页面下载模型后拖入 LM Studio 的模型文件夹。这样无法利用 LM Studio 本身的搜索功能。 本文将…

AI开发:用模型来识别手写数字的完整教程含源码 - Python 机器学习

今天一起来学习scikit-learn 。 scikit-learn 是一个强大的 Python 机器学习库&#xff0c;提供多种分类、回归、聚类算法&#xff0c;适用于从数据预处理到模型评估的全流程。它支持简单一致的 API&#xff0c;适合快速构建和测试模型。 官方地址在这里&#xff0c;记得Mark…

快速上手 RabbitMQ:使用 Docker 轻松搭建消息队列系统

在现代的分布式系统中&#xff0c;消息队列&#xff08;Message Queue&#xff09;是实现异步通信、解耦系统组件、提高系统可扩展性和可靠性的重要工具。RabbitMQ 是一个广泛使用的开源消息代理软件&#xff0c;它实现了高级消息队列协议&#xff08;AMQP&#xff09;&#xf…

任务管理法宝:甘特图详解

在项目管理中&#xff0c;如何清晰、直观地展示项目的进度和任务分配&#xff1f; 甘特图作为一种经典的项目管理工具&#xff0c;提供了有效的解决方案。无论是团队合作还是个人项目管理&#xff0c;甘特图都能帮助你轻松追踪各项任务的进展。今天&#xff0c;我们将详细介绍…

Keil5配色方案修改为类似VSCode配色

1. 为什么修改Keil5配色方案 视觉习惯&#xff1a;如果你已经习惯了VSCode的配色方案&#xff0c;尤其是在使用ESP-IDF开发ESP32时&#xff0c;Keil5的默认配色可能会让你感到不习惯。减少视觉疲劳&#xff1a;Keil5的默认背景可能过于明亮&#xff0c;长时间使用可能会导致视…

电子病历静态数据脱敏路径探索

一、引言 数据脱敏&#xff08;Data Masking&#xff09;&#xff0c;屏蔽敏感数据&#xff0c;对某些敏感信息&#xff08;比如patient_name、ip_no、ad、no、icd11、drug等等 &#xff09;通过脱敏规则进行数据的变形&#xff0c;实现隐私数据的可靠保护。电子病历作为医疗领…

【Linux | 计网】TCP协议深度解析:从连接管理到流量控制与滑动窗口

目录 前言&#xff1a; 1、三次握手和四次挥手的联系&#xff1a; 为什么挥手必须要将ACK和FIN分开呢&#xff1f; 2.理解 CLOSE_WAIT 状态 CLOSE_WAIT状态的特点 3.FIN_WAIT状态讲解 3.1、FIN_WAIT_1状态 3.2、FIN_WAIT_2状态 3.3、FIN_WAIT状态的作用与意义 4.理解…

矩阵加法        ‌‍‎‏

矩阵加法 C语言代码C 语言代码Java语言代码Python语言代码 &#x1f490;The Begin&#x1f490;点点关注&#xff0c;收藏不迷路&#x1f490; 输入两个n行m列的矩阵A和B&#xff0c;输出它们的和AB。 输入 第一行包含两个整数n和m&#xff0c;表示矩阵的行数和列数。1 <…

当大的div中有六个小的div,上面三个下面三个,当外层div高变大的时候我希望里面的小的div的高也变大

问&#xff1a; 当大的div中有六个小的div&#xff0c;上面三个下面三个&#xff0c;当外层div高变大的时候我希望里面的小的div的高也变大 回答&#xff1a; 这时候我们就不能写死六个小的div的高度&#xff0c;否则上下的小的div的间距就会变大&#xff0c;因为他们的高度…

C++打造局域网聊天室第一课:编程环境及准备知识

文章目录 前言一、使用环境二、基础知识1.MFC&#xff08;Microsoft Foundation Class&#xff09;2.API&#xff08;Application Programming Interface&#xff09;3.Unicode编码4.简单的比较5.WinSock6.多线程知识 总结 前言 C打造局域网聊天室第一课&#xff1a;编程环境及…

【网络安全】网站常见安全漏洞 - 网站基本组成及漏洞定义

文章目录 引言1. 一个网站的基本构成2. 一些我们经常听到的安全事件3. 网站攻击者及其意图3.1 网站攻击者的类型3.2 攻击者的意图 4. 漏洞的分类4.1 按来源分类4.2 按危害分类4.3 常见漏洞与OWASP Top 10 引言 在当今的数字化时代&#xff0c;安全问题已成为技术领域不可忽视的…

大数据项目-Django基于聚类算法实现的房屋售房数据分析及可视化系统

《[含文档PPT源码等]精品Django基于聚类算法实现的房屋售房数据分析及可视化系统》该项目含有源码、文档、PPT、配套开发软件、软件安装教程课程答疑等&#xff01; 数据库管理工具&#xff1a;phpstudy/Navicat或者phpstudy/sqlyog 后台管理系统涉及技术&#xff1a; 后台使…

SpringBoot如何使用EasyExcel实现表格导出(简洁快速入门版本)

前言 前面给大家介绍了动态表头的导入&#xff0c;这篇文章给大家介绍如何实现导出 前面给大家介绍了动态表头的导入&#xff0c;我们了解了如何通过EasyExcel灵活地读取结构不固定的Excel文件。这次&#xff0c;我们将目光转向数据导出——即如何将数据以Excel文件的形式输出…