NodeJS Koa 后端用户会话管理,JWT, Session,长短Token,本文一次性讲明白

前言

前几天,我写了一篇文章,《我设计的一个安全的 web 系统用户密码管理流程》。其中着重点是讲的如何利用非对称加密进行安全的设计,并在讲述了原理之后,又写了 《node 后端和浏览器前端,有关 RSA 非对称加密的完整实践, 前后端匹配的代码演示》 这篇文章,着重讲解了有关 RSA 非对称加密的完整实现。

但是,这些文章里并没有讲到用户登录管理的核心,也就是用户会话管理。这里面有很多概念,对于很多前端开发和很多初级后端开发来说,都是很模糊的。所以,今天,我想通过这一篇文章,把这里面的核心点全部讲明白。

基础概念

我们会听到一些词,大概是 SessionSession IDCookiesToken 等等,现在又有了新词儿,新的解决方案,如 JWT,长短 Token 等等。

我们一个一个来讲。这些词分别有对应的英文意思,但是每个词都有多个含义,并且在不同的环境下,还会有衍生不同的含义。因此,我这边只能从前后端开发的角度去解释这些名词,不能按照字典的含义去解释。

而且,由于网上言论众多,其中谬误的也好,佶屈聱牙的也罢,我都不去管它,我只按照我的理解来讲解,并且,我相信,我的理解是非常深入到位的。

Session

翻译——会话,引申为会话管理。那么,什么是会话呢?

首先,我们要理解一个基础概念——http 服务,是一种无状态服务。怎么理解无状态呢?一句话讲,就是——在默认情况下,后端程序根本不知道前端发过来的请求,谁是谁!

为了解决这个不知道谁是谁的问题,就引申出来解决方案——让后端程序知道,每一个请求,都是谁发出来的,好相应的把对应的资源发回去。

比如,张三请求 profile 接口,返回的内容应该 {name:"张三"},而不能是 {name:“李四”}。

那么,我们就可以理解,张三发出来的一系列的请求,应该归属于一个会话,李四发出来的一系列请求,应该归属于另一个会话。

所以,我们就需要把这一系列的会话,进行管理,这就是会话管理

换句话想,Session,并不是一个单纯的词,而是一个相对很大的概念,为了解决这个问题,不同的语言有不同的解决方案,这些各种不同的解决方案,都可以统称为 Session。

Session ID

理解了上面的 Session 的概念,这个概念就相对比较好理解了。每一个用户,都有一堆的资源,我们不能把这些资源都随时在程序里放着。因此,我们会把这些资源打包存着,然后整出一个 ID 来,方便我们来查询。这样,前端只要给我们这个 ID,我们就可以根据这个ID查找到对应的资源。

这里说的用户资源,是指 用户名,用户昵称,用户角色,过期时间等简短信息,只要方便后端程序快速的分清楚这货是谁,能干些啥事儿即可。不是说,要把所有的用户资源信息,全部存着。如果是那样的话,还要数据库干啥呢对吧。

Token

字面意思,凭证,令牌。是后端下发给前端的一段字符串(可长可短,你要愿意,给数字也不是不行,看你咋设计了。)

前端拿到这个 Token 以后,它每次发起请求时,都需要把这个 Token 给带上,后端根据这个 Token ,就可以去查找对应的资源了。

OK,注意到了吗?上面的 Session ID 是方便我们后端去查找资源的,这个 Token,也是后端去查找对应资源的。

所以—— Token = Session ID ?

答案是不一定。要看你咋设计。

一般而言,我是倾向于设计为 Token,就是 Session ID。当然,也可以不一样,前端给后端 Token,后端先根据 Token 去查找 SessionID,然后根据 ID 再查找对应资源,也是可以的对吧?

但我感觉这样设计有点缺心眼儿。

Cookies

字面意思是一种饼干,我不喜欢吃饼干,所以我不知道它具体是哪一种饼干。

Cookies 是用户浏览器的一种机制,它可以由我们的后端程序去设定。而且,在每次用户发起请求的时候,浏览器都会把 Cookies 自动带上。

换句话讲,如果我们使用 Cookies,可以大幅的减少前端开发的工作量,因为具体是咋实现的,不用管了,浏览器自动实现。

但问题是,现在的前端开发,往往不仅仅是运行在浏览器里面的网页,还有 APP、 小程序或者其他客户端程序,而这些里面,大多是没有 Cookies 的机制的。

因此,为了我们的后端服务可以同时服务多端,我建议就不要管这个玩意儿了。

不是不能用,顺手的时候,也可以兼容。

JWT

JSONWebToken 的缩写。在传统的会话管理里,都涉及一个存储的问题,就是,要把用户资源存着,然后去查询。你可以存在内存里,文件里,数据库里,等等,总之,你要存数据,并且方便查询。

JWT

假设,我们存在内存里,而我们的后端服务运行在多台负载均衡的服务器上,那么,当用户的 A 请求访问在甲服务器上,甲服务器在内存里存储了数据,B请求访问在乙服务器上,而乙服务器的内存中并没有用户数据,则会出现读取失败的问题。

怎么解决呢?聪明的你一定想到了解决方案——集中存储,比如单独搞一台 redis 服务器,大家都往这里存。挺好的。

那么假设你的这些服务器不在一个机房呢?也不是不能读是吧,就是慢点儿。

总之,传统的会话管理,有一个问题,就是 IO 问题,也就是存储和读取的问题。

JWT 方案是换了一个思路来解决,其核心原理是,直接将用户的资源信息加密,然后返回给客户端,客户端拿这个加密的长字符串直接作为 Token 来请求,后端程序只要解密字符串,就直接获得了用户的资源信息了。

也就是说, JWT 是用计算复杂度取代了存储复杂度,来解决上面说的问题。

总之,会话管理是一定要消耗资源的,要么是存储复杂度,要么是计算复杂度。


在很多文章和概念里,把 JWT 方案,和 Session 方案并列对比。可以这么比,但是我感觉概念不对。其实在我看来,JWT 方案,只是一种 Session 解决方案而已,两者是上下级的关系,而不是并列的关系。

我这边把传统的通过存储(你别管存哪儿,咋存)解决方案,称之为传统存储方案吧。

和传统存储方案相对比,优缺点如下

特点JWT存储
服务器状态无状态有状态
跨域支持天然支持需CORS配置
实时吊销默认不支持支持
传输效率大点儿,问题不大小,可忽略

其实总结下来,JWT最大的问题就是,一旦 Token 签发,除了超时失效,否则是没办法把用户登出的。

当然,聪明的你,肯定想到了黑名单机制,把登出的 Token 存下来,然后每次读取验证一下。那么我的问题是,那你为啥不用传统的存储会话管理,要用 JWT ?吃饱撑的?

长短 Token

好,通过上面的这些概念,我们知道,JWT 方案,不方便管理用户,传统存储解决方案,有IO性能问题,那么能不能两种方案结合结合,咱们取长补短!

可以,于是,有了长短 Token 的解决方案。

每次用户登录时,用 JWT 方式,签发一个长的 Token,这个 Token 的过期时间比较短,比如5分钟。5分钟后,它就失效了。

同时,用传统存储方案,签一个短的 Token。这个过期时间可以设置得比较长,比如一个月。

在正常业务时,后端直接读取用户传过来的 JWT 信息,就可以得到用户资源了。当前端发现 token 过期了,就拿 短 token 过来,再请求一个长 token,然后再继续使用。

这样,就解决了存储问题,又可以管理用户登出(直接在存储里删掉用户的短Token 即可)

代价是什么呢?代价是提高了各个前端项目的代码复杂度。你可以说,长短 Token 的解决方案是集合了两种解决方案的长处,也可以理解为,两者的短处也全粘上了。

传输数据变大,还是得存储用户信息,还消耗CPU计算资源等等。

小结

综上所述,我们应该对用户会话管理这块的概念都有了一个清晰的理解了。那么我们在开发项目时应该如何选择呢?

首先,无论是哪种解决方案,你都得会!没有什么方案是一招鲜,吃遍天的。

例如,传统存储方案中的所谓 IO 问题,对于绝大多数项目来说,这就是一个不存在的问题。直接往内存一存,有啥性能瓶颈?拢共就跑在一台服务器上,哪里来的什么速度或者进程共享的问题?在我看来,绝大多数项目,连 redis 都是多余。

再说,JWT 方案,有啥登出管理问题?一个小系统,一天登录拢共就几个人,你设置为有效期1天,我也不认为有多大的安全隐患,如果真遇到了什么大问题,直接把 JWT 的签发加密词一改,所有签发的TOKEN,全部失效。

最后说说长短 TOKEN,如果你团队有足够多的人手,项目也确实有很高的安全性,可以考虑使用。否则,是徒增麻烦。

所以,我推荐你根据你自己的项目选择合适的解决方案,我只说我的观点:

  1. 大多数项目都可以使用 JWT 方案。
  2. 你有切实的要迫使用户登出的项目,比如论坛等等,可以用传统的存储方案。
  3. 你团队实力足够,甲方是安全洁癖,项目也确实有高等级的要求,或者产品或老板想装逼忽悠客户,长短TOKEN你值得拥有!

本来,我是想在这篇文章中,引用一些代码,方便各位看官理解的,没想到,光讲概念就讲了这么多了。没办法,周末抽空,我会把每种方案的 NodeJS + Koa 的实战完整代码给写成文章分享给大家。


最近我在参加 CSDN 的一个创作比赛,各位看官在留言区留言可以给我加分。所以希望各位看官帮帮忙,点评一下哦!

当然,我们程序开发都是很忙滴,没时间点评没关系哈,点个赞,收个藏,也不是不可以哈!耽误不了您的事儿,还能让我继续保持创作热情,小可在这边谢谢各位看官了哈!

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

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

相关文章

0.5S 级精度背后:DJSF1352-RN-6 如何让储能电站的每 1kWh 都「有迹可循」?

1、背景 在能源转型的时代洪流里,大型储能电站作为保障电网稳定运行、平衡能源供需的核心基础设施,其战略价值愈发凸显。而储能电站的高效运转,始终离不开精准的电能计量体系支撑。今日为您重点推介一款针对 1500V 储能系统研发的专业电能表…

Linux运维笔记:服务器安全加固

文章目录 背景加固措施1. 修改用户密码2. 使用公钥认证替代密码登录3. 强化系统安全4. 扫描与清理残留威胁5. 规范软件管理(重点) 注意事项总结 提示:本文总结了大学实验室 Linux 电脑感染挖矿病毒后的安全加固措施,重点介绍用户密…

Pycharm 配置解释器

今天更新了一版pycharm,因为很久没有配置解释器了,发现一直失败。经过来回试了几次终于成功了,记录一下过程。 Step 1 Step 2 这里第二步一定要注意类型要选择python 而不是conda。 虽然我的解释器是conda 里面建立的一个环境。挺有意思的

【Linux】awk 命令详解及使用示例:结构化文本数据处理工具

【Linux】awk 命令详解及使用示例:结构化文本数据处理工具 引言 awk 是一种强大的文本处理工具和编程语言,专为处理结构化文本数据而设计。它的名称来源于其三位创始人的姓氏首字母:Alfred Aho、Peter Weinberger 和 Brian Kernighan。 基…

MS1023/MS1224——10MHz 到 80MHz、10:1 LVDS 并串转换器(串化器)/串并转换器(解串器)

产品简述 MS1023 串化器和 MS1224 解串器是一对 10bit 并串 / 串并转 换芯片,用于在 LVDS 差分底板上传输和接收 10MHz 至 80MHz 的并行字速率的串行数据。起始 / 停止位加载后,转换为负载编 码输出,串行数据速率介于 120Mbps…

跟我学c++中级篇——理解类型推导和C++不同版本的支持

一、类型推导 在前面反复分析过类型推导(包括前面提到的类模板参数推导CTAD),类型推导其实就是满足C语言这种强类型语言的要求即编译期必须确定对象的数据类型。换一句话说,理论上如果编译器中能够自动推导所有的相关数据类型&am…

vue3+TS+eslint9配置

记录eslint升级到9.x的版本之后遇到的坑 在 ESLint 9 中,配置方式发生了变化。Flat Config 格式(eslint.config.js 或 .ts)不再支持 extensions 选项。所以vscode编辑器中的 extensions 需要注释掉,要不然保存的时候不会格式化。…

书籍推荐 --- 《筚路维艰:中国经济社会主义路径的五次选择》

萧冬连.筚路维艰:中国社会主义路径的五次选择[M]. 前不久看完的这本书,还是蛮受震撼的。 这本书比较细致地(引用了很多的史料)、从中央高层的视角讲解了从新中国成立一直到改革开放初期这30多年里(1949---1980年代)发生在我国的几次重大事件(三大改造、第一个五年计…

C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)

名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序&#xff…

(三)动手学线性神经网络:从数学原理到代码实现

1 线性回归 线性回归是一种基本的预测模型,用于根据输入特征预测连续的输出值。它是机器学习和深度学习中最简单的模型之一,但却是理解更复杂模型的基础。 1.1 线性回归的基本元素 概念理解: 线性回归假设输入特征和输出之间存在线性关系。…

二十五、面向对象底层逻辑-SpringMVC九大组件之HandlerMapping接口设计

一、引言:MVC架构的交通枢纽 在Spring MVC框架中,HandlerMapping接口扮演着"请求导航仪"的关键角色,它决定了HTTP请求如何被路由到对应的Controller处理器。作为MVC模式的核心组件之一,HandlerMapping在请求处理的生命…

凌晨四点的星光

凌晨四点的城市像台停止运转的老旧机器,陈明裹紧外套踩着路灯的残影往家走。键盘敲击声仿佛还在耳边回响,他揉了揉酸涩的眼睛,手机屏幕突然亮起,是妻子发来的消息:“孩子又发烧了,我带他去医院。” 这是他…

Kyosan K5BMC ELECTRONIC INTERLOCKING MANUAL 电子联锁

Kyosan K5BMC ELECTRONIC INTERLOCKING MANUAL 电子联锁

LeetCode 热题 100 74. 搜索二维矩阵

LeetCode 热题 100 | 74. 搜索二维矩阵 大家好,今天我们来解决一道经典的算法题——搜索二维矩阵。这道题在 LeetCode 上被标记为中等难度,要求我们在一个满足特定条件的二维矩阵中查找一个目标值。如果目标值在矩阵中,返回 true&#xff1b…

如何在 HTML 中添加按钮

原文:如何在 HTML 中添加按钮 | w3cschool笔记 (请勿将文章标记为付费!!!!) 在网页开发中,按钮是用户界面中不可或缺的元素之一。无论是用于提交表单、触发动作还是导航&#xff0…

一篇文章实现Android图片拼接并保存至相册

系列文章目录 一篇文章实现Android图片拼接并保存至相册 文章目录 系列文章目录前言实现功能类定义和成员变量onCreate方法权限检查和图片选择处理选择的图片图片拼接功能图片保存功能 使用ImageStitcher类拼接图片代码解释:ImageStitcher.java类定义和方法计算拼接…

2025.06.06【Ribo-seq】|riboWaltz:P-site定位与三碱基周期性分析流程

文章目录 一、前言二、riboWaltz简介三、安装与依赖四、分析流程总览1. 数据准备2. 典型分析流程2.1 读取注释和BAM2.2 P-site定位2.3 三碱基周期性与元分析2.4 密码子使用偏好分析 五、可视化与结果解读六、常见问题与注意事项七、实战经验与建议八、参考资料九、结语 一、前言…

思维链的 内部机制和简单理解

思维链的 内部机制和简单理解 思维链是对解决问题的步骤进行规划,规划后将作为上下文 在LLM中继续输出。因为Transform都是一个一个单词生成,没新生成一个单词都会将新生的作为上下文。 可以这么理解,但更准确的简化描述是: 思维链是让模型在回答问题时,先“内部生成”或…

Charles 全流程指南:安装、设置、抓包与注意事项

Charles 是一款功能强大的网络抓包工具,支持 HTTP/HTTPS 流量监控、请求/响应分析、断点调试等功能。本文将从安装到实战抓包,提供完整流程及关键注意事项。 一、安装 Charles 官网下载:访问 Charles 官网,选择对应系统版本&…

全球长序列高分辨率光合有效辐射(PAR)(1984-2018)

时间分辨率:时空间分辨率:1km - 10km共享方式:开放获取数据大小:188.92 GB数据时间范围:1984-01-01 — 2018-12-31元数据更新时间:2022-04-29 数据集摘要 本数据集是一个包含接近35年(1984-201…