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

news2024/12/23 18:23:32

文章目录

  • 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 大小,但一般较小
性能自动随请求发送服务器需要维护状态,增加负担无状态机制,适合分布式应用
使用场景适合简单的用户状态管理适合需要存储大量用户数据的应用适合需要无状态认证和分布式系统的应用

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大数据新视界 -- Hive 元数据管理:核心元数据的深度解析(上)(27 / 30)

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

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

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

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

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

ELK的Filebeat

目录 传送门前言一、概念1. 主要功能2. 架构3. 使用场景4. 模块5. 监控与管理 二、下载地址三、Linux下7.6.2版本安装filebeat.yml配置文件参考&#xff08;不要直接拷贝用&#xff09;多行匹配配置过滤配置最终配置&#xff08;一、多行匹配、直接读取日志文件、EFK方案&#…

UE5 像素流进行内网https证书创建

确定证书需求 内网 HTTPS 通信通常需要以下内容&#xff1a; 自签名证书&#xff08;适用于内网环境&#xff0c;不需要通过公开的证书颁发机构 CA&#xff09; 或者通过内部的企业 CA 签发的证书&#xff08;更安全&#xff09;。 生成自签名证书 使用工具&#xff08;如 Ope…

44页PDF | 信息化战略规划标准框架方法论与实施方法(限免下载)

一、前言 这份报告详细介绍了企业信息化战略规划的标准框架、方法论以及实施方法&#xff0c;强调了信息化规划应以业务战略和IT战略为驱动力&#xff0c;通过构筑企业架构&#xff08;EA&#xff09;来连接长期战略和信息化建设。报告提出了信息化规划原则&#xff0c;探讨了…

RNACOS:用Rust实现的Nacos服务

RNACOS是一个使用Rust语言开发的Nacos服务实现&#xff0c;它继承了Nacos的所有核心功能&#xff0c;并在此基础上进行了优化和改进。作为一个轻量级、快速、稳定且高性能的服务&#xff0c;RNACOS不仅包含了注册中心、配置中心和Web管理控制台的功能&#xff0c;还支持单机和集…

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

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

RabbitMQ 客户端 连接、发送、接收处理消息

RabbitMQ 客户端 连接、发送、接收处理消息 一. RabbitMQ 的机制跟 Tcp、Udp、Http 这种还不太一样 RabbitMQ 服务&#xff0c;不是像其他服务器一样&#xff0c;负责逻辑处理&#xff0c;然后转发给客户端 而是所有客户端想要向 RabbitMQ服务发送消息&#xff0c; 第一步&a…

PyQt 中的无限循环后台任务

在 PyQt 中实现一个后台无限循环任务&#xff0c;需要确保不会阻塞主线程&#xff0c;否则会导致 GUI 无响应。常用的方法是利用 线程&#xff08;QThread&#xff09; 或 任务&#xff08;QRunnable 和 QThreadPool&#xff09; 来运行后台任务。以下是一些实现方式和关键点&a…

云计算vsphere 服务器上添加主机配置

这里是esxi 主机 先把主机打开 然后 先开启dns 再开启 vcenter 把每台设备桌面再vmware workstation 上显示 同上也是一样 &#xff0c;因为在esxi 主机的界面可能有些东西不好操作 我们选择主机和集群 左边显示172.16.100.200

Python酷库之旅-第三方库Pandas(255)

目录 一、用法精讲 1206、pandas.tseries.offsets.SemiMonthEnd.is_on_offset方法 1206-1、语法 1206-2、参数 1206-3、功能 1206-4、返回值 1206-5、说明 1206-6、用法 1206-6-1、数据准备 1206-6-2、代码示例 1206-6-3、结果输出 1207、pandas.tseries.offsets.S…

Envoy-istio

最近研究envoy-istio&#xff0c;发现这个博客&#xff0c;觉得很不错&#xff0c;这里记录一下 envoy-istio介绍 envoy-istio - 随笔分类 - yaowx - 博客园 envoy部分七&#xff1a;envoy的http流量管理基础 envoy部分六&#xff1a;envoy的集群管理 envoy部分五&#xff…

甘特图的绘制步骤:教你如何绘制甘特图

甘特图是项目管理中一种极为重要的可视化工具&#xff0c;它以直观的方式展示项目进度&#xff0c;包括任务的开始时间、结束时间、持续时长以及任务之间的先后顺序。在当今的项目管理领域&#xff0c;Excel 和专业的项目管理软件是制作甘特图的两大常用途径&#xff0c;它们各…

C++模拟堆

模板题目 图片来源Acwing 堆的基础知识 代码实现 #include<iostream> #include<algorithm>using namespace std;const int N 1e5 10; int a[N]; int n, m;void down(int u) {int t u;if (2 * u < n && a[2 * u] < a[u]){t 2 * u;}if (2 * u …

牛客linux

1、 统计文件的行数 # 方法 1 wc -l ./nowcoder.txt | awk {print $1} # 方法 2 &#xff0c;awk 可以打印所有行的行号, 或者只打印最后一行 awk {print NR} ./nowcoder.txt |tail -n 1 awk END{print NR} ./nowcoder.txt # 方法 3 grep -c 、-n等等 grep -c "" ./…

【unity小技巧】在 Unity 中,Application获取各种文件路径或访问不同类型的存储路径

文章目录 前言1. **Application.persistentDataPath**2. **Application.dataPath**3. **Application.streamingAssetsPath**4. **Application.temporaryCachePath**5. **Application.consoleLogPath**6. **Application.userDataPath**7. **Application.streamingAssetsPath 与 …

汇编语言学习-二

好吧&#xff0c;已经隔了两天&#xff0c;下完班看了两天&#xff0c;在电脑上装了虚拟机版的MS_DOS,主要是怕折腾坏我的电脑系统&#xff1b; 这个第二天应该是称为第二章更为合适&#xff0c;目前第二章已经看完&#xff0c;基本的命令也是敲了敲&#xff1b; 下面就进行一…

游戏引擎学习第33天

仓库: https://gitee.com/mrxiao_com/2d_game 位置表示的回顾 在之前的工作中&#xff0c;已经实现了将单位从像素空间转移到真实的空间&#xff0c;这样可以确保所有的动作和物体都按米为单位来进行。这个转变让游戏中的物体不再是基于像素的&#xff0c;而是按照真实世界的…

泷羽sec-burp(3)decodor comparer logger模块使用 学习笔记

声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&a…