深入解析Cookie、Session以及Token原理

一、概述

1.1 HTTP无状态问题

目前主流的服务采用的是B\S架构,即浏览器\服务端架构。一般采用的协议是HTTP,HTTP有个特点是无状态,即在一次连接,两次成功请求之间没有任何的关系。这个特性既带来了一定的优点,在某些场景下也有不足。

优点:因为服务器不会去记录HTTP的状态,所以不需要额外的资源来记录状态信息,减轻了服务器的负担
缺点:因为没有记忆能力,如果后续操作需要前面的信息,必须重传,效率低。例如,用户在进行购物时,用户将某一个商品加入购物车,切换页面后,再次添加另一个商品,者两次添加商品的请求之间没有任何关系。因此,浏览器就无法知道用户最终选择了哪些商品。可使用HTTP的头部进行扩展来解决此问题。

1.2 解决方案

目前主要有三种主流的解决方案:Cookie机制、Session机制以及Token机制

二、三种机制的原理

2.1 Cookie机制原理

2.1.1 特点

  1. 服务器发送到浏览器,并保存到浏览器的一小块数据;
  2. 浏览器下次访问该服务器时,会自动携带该块数据,将其发送给服务器。
  3. 主要用于服务器判断请求是否来自同一个浏览器。

2.1.2 原理

核心机制:通过在请求和响应报文中写入Cookie信息来控制客户端的状态

  1. 当客户端第一次向服务器请求信息时,后端服务器会将需要验证的信息以Key-Value的形式放入Cookie中,并将Cookie放入到响应报文中,客户端会解析响应报文取出Cookie并保存Cookie;
  2. 当该客户端再次向服务器发送请求报文时,会在请求报文中添加Cookie信息,服务器在收到请求报文时,会解析Cookie中的信息,判断是否和预期设置的验证信息一致,进而达到不同请求之间的数据互通。

2.1.3 优缺点

优点:1. 可配置到期时间;2. 简单性:Cookie是一种基于文本的轻量结构,包含简单的键值对;3. 数据持久性:Cookie在过期之前一直存储在客户端浏览器上。
缺点:1. 大小受限制:大多数浏览器对Cookie的大小有4K、8K的限制;2. 用户配置Cookie禁用:有些用户会在浏览器客户端禁用Cookie的能力;3. 安全性差:Cookie由于存在在浏览器,有可能会被篡改

2.1.4 代码实现

/*
* 服务器生成Cookie
* */
@RequestMapping(path = "/cookie/set", method = RequestMethod.GET)
@ResponseBody
public String setCookie(HttpServletResponse response) {Cookie cookie = new Cookie("code", CommunityUtil.generateUUID()); // 存在验证信息cookie.setMaxAge(60 * 10); // 设置过期时间cookie.setPath("/community/alpha"); // 设置生效路径response.addCookie(cookie); // 将Cookie放入到响应报文中return "set cookie";
}/** 浏览器发送Cookie* */
@RequestMapping(path = "/cookie/get", method = RequestMethod.GET)
@ResponseBody
public String getCookie(@CookieValue("code") String code) {System.out.println(code);return "get cookie";
}

2.2 Session机制原理

2.2.1 特点

  1. 在服务端保存客户端的信息;
  2. Session指的是同一个浏览器发起的多次请求,一旦会话关闭,Session也会被销毁;
  3. 服务器会为每一次会话分配一个Session对象。

2.2.2 原理

核心机制:服务器端生成一个Session,存储浏览器的各种信息,同时有唯一的一个sessionId,服务器通过识别这个sessionId来实现业务的连续

  1. 打开第一次会话时,服务器会默认生成一个Session,服务器将各种信息存放在Session中,同时服务器端隐式的生成一个Cookie用于存放SessionId,会放在响应报文中返回给浏览器,浏览器会保存Cookie;
  2. 同一个会话下,每次请求都会将SessionId放入到Cookie中,发送给服务器,服务器就可以解析Session获取需要的信息。

2.2.3 优缺点

优点:解决了Cookie存放数据大小的限制, 同时数据保存在服务器, 安全性更高
缺点:大量的Session数据存放在服务器, 占用很大的内存

扩展:实际生产环境中如何使用Session?

背景:现实生活中多采用分布式集群架构,中间利用NGINX保证负载均衡;若服务器A为此请求生成了session,下一次请求时,因NGINX可能会请求到另一台服务器上,重新生成Session,无法获取到上一次请求的信息,同时占用大量内存。
解决方案:设置分配策略
1. 黏性Session:记住上次访问主机的IP地址,下一次同一请求,还来请求这台服务器;【缺点:无法保证负载均衡】
2. 同步Session: 每生成一个session,在服务器集群中同步该session;【缺点:1. 同步对服务器产生性能影响;2.服务器之间产生耦合,对部署不利。】
3. 共享Session: 专门设置一台服务器,用于存放Session;【缺点:单机存在性能瓶颈,一旦宕机,则无法使用】
利用数据库[推荐使用]:大部分存在浏览器中,敏感数据直接放在Mysql数据库集群中;【缺点:数据存放在硬件中,性能低】==> 优化:利用Redis数据库存放

2.2.4 代码实现

/*
* 服务器端生成session
* */
@RequestMapping(path = "/session/set", method = RequestMethod.GET)
@ResponseBody
public String setSession(HttpSession session) {session.setAttribute("id", 1);session.setAttribute("name", "test");return "set session";
}/** 浏览器发送请求的时候session* */
@RequestMapping(path = "/session/get", method = RequestMethod.GET)
@ResponseBody
public String getSession(HttpSession session) {session.getAttribute("id");session.getAttribute("name");return "get session";
}

2.3 Token机制原理

2.3.1 特点

JWT(JSON Web Token)是一种开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。这些信息可以被验证和信任,因为它们是数字签名的,不需要存储在服务器端。

2.3.2 原理

JWT主要由三部分组成:Header、PayLoad和Signature,每一部分通过"."分割。例如:

xxxx.yyyyy.zzzzzz

Header由两部分组成:算法和类型。例如:

{”alg“: "HS256","typ": "JWT"
}

上述JSON数据会被encode成Base64Url, 作为JWT第一部分设置。
PayLoad:载荷,即存放有效信息的地方,是一组claim值。claim包含claim name和claim value,前者是String类型,后者可以是任意的json对象。claims有三种类型:reserved claim,public claim和private claim,类似于Java中的权限控制符。例如:

{"sub": "27927692","name":John,"admin": true
}

上述JSON也会被encode成Base64Url, 作为第二部分设置。
Signature: 签名,用点号将header和payload关联起来,用header中指定的加密算法对字符串进行加密。例如:

signature = HAMCHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret密钥)

最佳实践:在客户端和服务端之间的传输将JWT设置在HTTP header里,一般名称设置为Authorization的header, 具体格式如下:

Authorization: Bearer <token>Beaer之后有个空格

2.3.3 代码实现

	// 生成JWT Token@Testpublic void testGengerateJWT() {String jwtToken = Jwts.builder()// set header.setHeaderParam("typ", "JWT").setHeaderParam("alg", "HS256")// set payload.claim("username", "tom").claim("role", "admin").setSubject("admin-role-test")// set expired time 有效期.setExpiration(new Date(System.currentTimeMillis() + time)).setId(UUID.randomUUID().toString())// set signature.signWith(SignatureAlgorithm.HS256, secert).compact();System.out.println(jwtToken);}// 获取JWT Token信息以及验证Token的有效性@Testpublic void testCheckJwtToken() {String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6InRvbSIsInJvbGUiOiJhZG1pbiIsInN1YiI6ImFkbWluLXJvbGUtdGVzdCIsImV4cCI6MTcxMzMxOTA1NSwianRpIjoiNzViNjlhYTUtNjBmYy00NGQwLWJmYjctZGIyMWRhZWE4MDQ1In0.pg7F_gN9r6gZuMie4Ibs6IYjfvVAbywMcSSQtdUA27s";JwtParser parser = Jwts.parser();Claims claims = parser.setSigningKey(secert).parseClaimsJws(token).getBody();System.out.println(claims.get("username"));System.out.println(claims.get("role"));System.out.println(claims.getExpiration());}

三、三种机制的区别和联系

  1. 是否支持跨域:JWT支持跨域,Cookie和Session不支持跨域,只能在当前域和子域中使用;
  2. 存储位置:JWT放在HTTP header中, Cookie放在客户端,Session放在服务端;
  3. 安全性:JWT 的安全性高于Session和Cookie
  4. 性能: JWT中放在Header中,若存放信息过多,会使得整个网络流量非常大,但不占用内存,不过需要耗费解析Token的时间;Session耗费服务器的内存;Cookie放在客户端,相对来说占用内存较小。
  5. 原理:JWT Token是使服务端无状态化的机制,不会存储会话信息,支持服务负载均衡;Session使服务端有状态化,会存储会话信息,在分布式情况下,无法负载均衡
  6. 应用场景:JWT比较适合移动端(不支持Cookie)和内部系统,跨域认证、API接口鉴权等场景,特别是在微服务架构和分布式系统中。

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

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

相关文章

Struts2的入门:新建项目——》导入jar包——》jsp,action,struts.xml,web.xml——》在项目运行

文章目录 配置环境tomcat 新建项目导入jar包新建jsp界面新建action类新建struts.xml,用来配置action文件配置Struts2的核心过滤器&#xff1a;web.xml 启动测试给一个返回界面在struts.xml中配置以实现页面的跳转&#xff1a;result再写个success.jsp最后在项目运行 配置环境 …

【数据分享】我国第七次人口普查的100m分辨率人口栅格数据(免费获取\tif格式\2020年)

人口空间分布数据是我们在各项研究中经常使用的数据。之前我们分享过来源于LandScan数据集的2000-2022年的1km精度的人口空间分布栅格数据&#xff08;可查看之前的文章获悉详情&#xff09;&#xff01; 相较于LandScan全球人口数据集&#xff0c;我国历次人口普查的数据对于…

SpringBoot通用模块--文件上传开发(阿里云OSS)

文件上传&#xff0c;是指将本地图片、视频、音频等文件上传到服务器上&#xff0c;可以供其他用户浏览或下载的过程。文件上传在项目中应用非常广泛&#xff0c;我们经常发抖音、发朋友圈都用到了文件上传功能。 实现文件上传服务&#xff0c;需要有存储的支持&#xff0c;那…

基于支持 GPT 的服务的初创公司

Kafkai&#xff1a;多语言长篇内容生成&#xff0c;AI写作的新趋势 介绍 随着生成式预训练 Transformer (GPT) 的出现&#xff0c;技术世界正在见证范式转变。 这种人工智能驱动的创新不仅仅是一种转瞬即逝的趋势&#xff0c;而是一种趋势。 它已成为科技行业的基石&#xff0c…

部分国企笔试总结

2024.3.30相城区某国企笔试 客观题&#xff0c;30分 类似考公行测题&#xff08;大部分&#xff09;部分计算机专业基础知识&#xff08;仅几题&#xff09; 主观题&#xff0c;70分 网络安全类一道C编程题&#xff1a;用户输入圆半径r&#xff0c;程序计算面积和周长并输出…

【C语言】简单介绍进制和操作符

&#x1f308;个人主页&#xff1a;是店小二呀 &#x1f308;C语言笔记专栏&#xff1a;C语言笔记 &#x1f308;C笔记专栏&#xff1a; C笔记 &#x1f308;喜欢的诗句:无人扶我青云志 我自踏雪至山巅 本文简要介绍进制和操作符&#xff0c;愿能为您提供帮助&#xff01;文章…

异常的种类

Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 Oracle 运行时错误可以分为 Oracle 错误和用户自定义错误&#xff0c;与此对应&#xff0c;根据异常产生的机制和原理&#xff0c;可将 Oracle 的系统异常分为 3 种 预定义…

【Linux】libgpiod使用方法

1、libgpiod库的移植 参见本人博客:libgpiod库的移植 2、libgpiod使用 2.1 打开GPIO芯片 一个GPIO芯片管理N个GPIO,每个GPIO芯片用结构体 ==gpiod_chip == 来表示。 1)以路径方式打开 例如GPIO芯片的路径为:/dev/gpiochip0 struct gpiod_chip *gpiod_chip_open(const …

使用VPN时,Java程序无法访问远程网络的解决办法

应用场景&#xff1a; 电脑连接VPN之后&#xff0c;Java程序无法连接远程服务&#xff0c;比如第三方接口、远程数据库连接、远程微服务等。我个人遇到的情况有连接海康威视SDK&#xff0c;influxdb以及一些微服务。 解决办法&#xff1a; 启动Java时加入参数&#xff1a;-D…

一个嵌入式ucosII系统的典型代码范例

在嵌入式系统开发中&#xff0c;uC/OS-II是一个非常流行的实时操作系统。它提供了许多功能&#xff0c;包括任务管理、信号量、消息邮箱、事件标志等&#xff0c;使得开发者能够更轻松地实现复杂的系统功能。在本文中&#xff0c;我们将展示一个完整的uC/OS-II示例代码&#xf…

41.Python从入门到精通—格式化日期 获取某月日历 Time 模块 日历(Calendar)模块 其他相关模块和函数

41.Python从入门到精通—格式化日期 获取某月日历 Time 模块 日历&#xff08;Calendar&#xff09;模块 其他相关模块和函数 格式化日期获取某月日历Time 模块日历&#xff08;Calendar&#xff09;模块其他相关模块和函数 格式化日期 在 Python 中&#xff0c;可以使用 strf…

比较好玩的车子 高尔夫6

https://www.sohu.com/a/484063087_221273 四万多如愿收获手动挡高尔夫6&#xff0c;可靠性、经济性、操控性兼顾_搜狐汽车_搜狐网 2.基本上其他人也不知道到底是什么相关的车子信息

基于单片机和ICL7135多档位数字电压表设计

**单片机设计介绍&#xff0c;基于单片机和ICL7135多档位数字电压表设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机和ICL7135的多档位数字电压表设计是一个结合了硬件与软件技术的综合性项目。这种设计旨在实现一…

四种锁(互斥锁,递归锁,读写锁,自旋锁)

1.互斥锁(mutex):互斥锁是最常见的一种锁,用来保护共享资源的互斥访问。一次只有一个线程可以获得互斥锁。如果其他线程试图获得已经被锁定的互斥锁,他们将被阻塞,直到锁被释放 2.递归锁(recursive lock):递归锁是一种特殊的互斥锁,允许同一个线程多次获得同一个锁,而不会导致死…

[lesson12]经典问题解析一

经典问题解析一 关于const的疑问 const常量的判别准则 只有用字面量初始化的const常量才会进入符号表使用其他变量初始化的const常量仍然是只读变量被volatile修饰的const常量不会进入符号表 在编译期间不能直接确定初始值的const标识符&#xff0c;都被作为只读变量处理 con…

Pnpm + Turbo 搭建 Web Component Monorepo 组件库

技术选型 使用 Pnpm Turbo 搭建 Web Component Monorepo项目 stencil-component-ui 组件库 pnpm 作为包管理器Turborepo 作为构建系统Vitepress 管理文档 pnpm 技术 什么是 pnpm? 它有哪些优势&#xff1f; pnpm 跟 npm、yarn一样&#xff0c;都是用于管理Node包依赖的管…

iOS App Store审核要求与Flutter应用的兼容性分析

本文探讨了使用Flutter开发的iOS应用能否上架&#xff0c;以及上架的具体流程。苹果提供了App Store作为正式上架渠道&#xff0c;同时也有TestFlight供开发者进行内测。合规并通过审核后&#xff0c;Flutter应用可以顺利上架。但上架过程可能存在一些挑战&#xff0c;因此可能…

云岚到家项目

一.项目介绍 云岚到家项目是一个家政服务o2o平台&#xff0c;互联网家政是继打车、外卖后的又一个风口&#xff0c;创业者众多&#xff0c;比如&#xff1a;58到家&#xff0c;天鹅到家等&#xff0c;o2o&#xff08;Online To Offline&#xff09;是将线下商务的机会与互联网…

openharmony launcher 调研笔记(03)UI 数据装配

最近在看launcher&#xff0c;把自己调研的点做个笔记&#xff0c;持续修改更新中&#xff0c;个人笔记酌情参考。 桌面上半部分包含父子逻辑&#xff1a; Column() { PageDesktopLayout(); } PageDesktopLayout->GridSwiper->Swiper->SwiperPage 1.PageDe…

25.11 MySQL 视图

1. 常见的数据库对象 对象描述表(TABLE)存储数据的逻辑单元, 以行和列的形式存在, 列就是字段, 行就是记录.数据字典系统表, 存放数据库相关信息的表. 数据通常由数据库系统维护, 程序员通常不可修改, 只可查看.约束(CONSTRAINT)执行数据校验的规则, 用于保证数据完整性的规则…