首页 > 其他分享 >计算机基础---Cookie、Session、Token的区别

计算机基础---Cookie、Session、Token的区别

时间:2024-11-25 09:33:04浏览次数:9  
标签:session 请求 用户 token server --- Token Session 购物车

Cookie

Cookie 是一种存储在用户浏览器中的小型文本文件,用于保存用户信息和偏好。主要用于记住用户的登录状态、购物车内容、用户偏好等。

以加入购物车为例,每次浏览器请求后 server 都会将本次商品 id 存储在 Cookie 中返回给客户端,客户端会将 Cookie 保存在本地,下一次再将上次保存在本地的 Cookie 传给 server 就行了,这样每个 Cookie 都保存着用户的商品 id,购买记录也就不会丢失了

image.png

cookie的问题:

但是随着购物车内的商品越来越多,每次请求的 cookie 也越来越大,这对每个请求来说是一个很大的负担,我只是想将一个商品加入购买车,为何要将历史的商品记录也一起返回给 server ?购物车信息其实已经记录在 server 了,浏览器这样的操作岂不是多此一举?怎么改进呢?

Session

Session 是一种服务器端机制,用于存储用户会话期间的数据。通常用于跟踪用户会话状态,如登录状态、用户操作等。

仔细考虑下,由于用户的购物车信息都会保存在 Server 中,所以在 Cookie 里只要保存能识别用户身份的信息,知道是谁发起了加入购物车操作即可,这样每次请求后只要在 Cookie 里带上用户的身份信息,请求体里也只要带上本次加入购物车的商品 id,大大减少了 cookie 的体积大小,我们把这种能识别哪个请求由哪个用户发起的机制称为 Session(会话机制),生成的能识别用户身份信息的字符串称为 sessionId,它的工作机制如下
image.png|525

  1. 首先用户登录,server 会为用户生成一个 session,为其分配唯一的 sessionId,这个 sessionId 是与某个用户绑定的,也就是说根据此 sessionid(假设为 abc) 可以查询到它到底是哪个用户,然后将此 sessionid 通过 cookie 传给浏览器
  2. 之后浏览器的每次添加购物车请求中只要在 cookie 里带上 sessionId=abc 这一个键值对即可,server 根据 sessionId 找到它对应的用户后,把传过来的商品 id 保存到 server 中对应用户的购物车即可

可以看到通过这种方式再也不需要在 cookie 里传所有的购物车的商品 id 了,大大减轻了请求的负担!

另外通过上文不难观察出 cookie 是存储在 client 的,而 session 保存在 server,sessionId 需要借助 cookie 的传递才有意义。

session的问题:

看起来通过 cookie + session 的方式是解决了问题, 但是我们忽略了一个问题,上述情况能正常工作是因为我们假设 server 是单机工作的,但实际在生产上,为了保障高可用,一般服务器至少需要两台机器,通过负载均衡的方式来决定到底请求该打到哪台机器
image.png|350

如图示:客户端请求后,由负载均衡器(如 Nginx)来决定到底打到哪台机器

假设登录请求打到了 A 机器,A 机器生成了 session 并在 cookie 里添加 sessionId 返回给了浏览器,那么问题来了:下次添加购物车时如果请求打到了 B 或者 C,由于 session 是在 A 机器生成的,此时的 B,C 是找不到 session 的,那么就会发生无法添加购物车的错误,就得重新登录了,此时请问该怎么办。主要有以下三种方式:

1、session 复制

A 生成 session 后复制到 B, C,这样每台机器都有一份 session,无论添加购物车的请求打到哪台机器,由于 session 都能找到,故不会有问题

image.png|425

这种方式虽然可行,但缺点也很明显:

  • 同一样的一份 session 保存了多份,数据冗余
  • 如果节点少还好,但如果节点多的话,造成的性能消耗也会很大。

2、session 粘连

这种方式是让每个客户端请求只打到固定的一台机器上,比如浏览器登录请求打到 A 机器后,后续所有的添加购物车请求也都打到 A 机器上,Nginx 的 sticky 模块可以支持这种方式,支持按 ip 或 cookie 粘连等等
image.png|450

这样的话每个 client 请求到达 Nginx 后,只要它的 ip 不变,根据 ip hash 算出来的值会打到固定的机器上,也就不存在 session 找不到的问题了,当然不难看出这种方式缺点也是很明显,对应的机器挂了怎么办?

3、session 共享

这种方式也是目前各大公司普遍采用的方案,将 session 保存在 redis,memcached 等中间件中,请求到来时,各个机器去这些中间件取一下 session 即可。
image.png|450

缺点其实也不难发现,就是每个请求都要去 redis 取一下 session,多了一次内部连接,消耗了一点性能,另外为了保证 redis 的高可用,必须做集群,当然了对于大公司来说, redis 集群基本都会部署,所以这方案可以说是大公司的首选了。

Token

使用Token时的流程:
image.png|425

看了上图会发现存在两个问题

1、 token 只存储在浏览器中,服务端却没有存储,这样的话我随便搞个 token 传给 server 也行?

答:server 会有一套校验机制,校验这个 token 是否合法。

2、怎么不像 session 那样根据 sessionId 找到 userid 呢,这样的话怎么知道是哪个用户?

答:token 本身携带 uid 信息

可以看到 token 主要由三部分组成

  • header:指定了签名算法
  • payload:可以指定用户 id,过期时间等非敏感数据
  • Signature: 签名,server 根据 header 知道它该用哪种签名算法,再用密钥根据此签名算法对 head + payload 生成签名,这样一个 token 就生成了。

当 server 收到浏览器传过来的 token 时,它会首先取出 token 中的 header + payload,根据密钥生成签名,然后再与 token 中的签名比对,如果成功则说明签名是合法的,即 token 是合法的。而且你会发现 payload 中存有我们的 userId,所以拿到 token 后直接在 payload 中就可获取 userid,避免了像 session 那样要从 redis 去取的开销

画外音:header, payload 实际上是以 base64 的形式存在的,文中为了描述方便,省去了这一步。

你会发现这种方式确实很妙,只要 server 保证密钥不泄露,那么生成的 token 就是安全的,因为如果伪造 token 的话在签名验证环节是无法通过的,就此即可判定 token 非法。

可以看到通过这种方式有效地避免了 token 必须保存在 server 的弊端,实现了分布式存储,不过需要注意的是,token 一旦由 server 生成,它就是有效的,直到过期,无法让 token 失效,除非在 server 为 token 设立一个黑名单,在校验 token 前先过一遍此黑名单,如果在黑名单里则此 token 失效,但一旦这样做的话,那就意味着黑名单就必须保存在 server,这又回到了 session 的模式,那直接用 session 不香吗。
**所以一般的做法是当客户端登出要让 token 失效时,直接在本地移除 token 即可,下次登录重新生成 token 就好。

另外需要注意的是 token 一般是放在 header 的 Authorization 自定义头里,不是放在 Cookie 里的,这主要是为了解决跨域不能共享 Cookie 的问题

标签:session,请求,用户,token,server,---,Token,Session,购物车
From: https://blog.csdn.net/weixin_73205368/article/details/143998065

相关文章

  • 说说你对min-width和max-width的理解,它们有什么运用场景?
    min-width和max-width是CSS属性,用于控制元素的最小和最大宽度。它们在响应式网页设计中非常重要,可以确保元素在不同屏幕尺寸下都能良好地显示。min-width(最小宽度):定义:指定元素内容区域的最小宽度。即使内容较少,元素的宽度也不会小于min-width的值。作用:避免元......
  • Spring---Bean的生命周期
    什么是Bean的生命周期Bean的生命周期就是:对象从创建开始到最终销毁的整个过程,Bean对象从创建到销毁中经历了哪些过程什么时候创建Bean对象?创建Bean对象的前后会调用什么方法?Bean对象什么时候销毁?Bean对象的销毁前后调用什么方法?Spring其实就是一个管理Bean对象的工厂,它负......
  • python-爬虫入门指南
    前言:由于个人负责的运维组,其中有个同事每回在某个项目发版更新后,需手动在k8s容器平台web界面上复制出几百个微服务的名称以及镜像版本等信息,用来更新微服务清单,个人决定抽时间写个爬虫脚本自动完成手动执行的任务。由于公司信息需保密,这里介绍个简单入门的爬虫脚本做为范例......
  • HarmonyOs DevEco Studio小技巧34--鸿蒙应用架构设计 MVVM模式与三层架构、工程目录迁
    MVVM模式ArkUI采取MVVM=Model+View+ViewModel模式,其中状态管理模块起到的就是ViewModel的作用,将数据与视图绑定在一起,更新数据的时候直接更新视图。在MVVM模式中:Model(模型):model文件夹用于存储数据模型。它表示组件或其他相关业务逻辑之间传输的数据,是对原始数据的......
  • OpenCV-Python 特征匹配
    37.1Brute-Force匹配的基础蛮力匹配器是很简单的。首先在第一幅图像中选取一个关键点然后依次与第二幅图像的每个关键点进行(描述符)距离测试,最后返回距离最近的关键点。对于BF匹配器,我们首先要使用cv2.BFMatcher()创建一个BFMatcher对象。它有两个可选参数。第......
  • # 学期(如2024-2025-1) 学号(如:20241402) 《计算机基础与程序设计》第10周学习总结
    学期(如2024-2025-1)学号(如:20241402)《计算机基础与程序设计》第10周学习总结作业信息这个作业属于哪个课程<班级的链接>(如2024-2025-1-计算机基础与程序设计)这个作业要求在哪里<作业要求的链接>(如2024-2025-1计算机基础与程序设计第一周作业)这个作业的目标<写上......
  • 请举例说明伪元素 (pseudo-elements) 有哪些用途?
    伪元素在前端开发中用途广泛,以下是一些常见的例子:1.样式化特定内容:::before和::after可以用来插入生成的内容,例如图标、计数器、引号等。.quote::before{content:open-quote;}.quote::after{content:close-quote;}::first-letter可以用来样式化第一......
  • 2024/11/30--阅读笔记|人月神话————画蛇添足
    画蛇添足——蛇本来没有脚,先画成蛇的人,却将蛇添了脚,结果不成为蛇。蛇本来没有脚却被人给它强行加上脚,比喻做事多此一举,反而坏事。我们在成功来临的时候,要保持和巩固现有的成果,不能多次一举,耍小聪明、炫耀自己,否则就会惨败。自作聪明、做多余的事,反而会弄巧成拙,把事情办糟。......
  • Figma入门-文字、样式、链接、动作
    Figma入门-文字、样式、链接、动作前言在之前的工作中,大家的原型图都是使用Axure制作的,印象中Figma一直是个专业设计软件。最近,很多产品朋友告诉我,很多原型图都开始用Figma制作了,并且很多组件都是内置的,对各种原型图的制作及其友好,只需熟悉一下基本的操作即可上手。......
  • python - 验证身份证合法性
    可以使用id_validator库1.验证身份证号合法性验证身份证号是否合法,合法返回True,不合法返回Falsefromid_validatorimportvalidatorvalidator.is_valid('440308199901101512')#大陆居民身份证18位validator.is_valid('610104620927690')#大陆居民身份证15位......