jwt 与 sessionid 的区别及应用场景
在现代 Web 应用中,JWT(JSON Web Token)和SessionID是两种常用的用户认证和状态管理机制。本文从两者的原理、区别、优缺点以及适用场景展开分析,结合常见问题提出了最佳实践建议,帮助开发者更好地选择和使用。
JWT与SessionID的区别及应用场景详解
在现代web应用开发中,JWT(JSON Web Token)和SessionID是两种常用的身份验证机制。本文将从原理、应用场景、优缺点等角度深入剖析二者,帮助开发者在实际项目中做出合适的选择。
1. 原理解析
1.1 SessionID
-
工作流程:
- 用户登录后,服务器在内存中创建会话,并生成唯一的
SessionID。 SessionID返回给客户端(通常通过 Cookie 存储)。- 客户端每次请求时,携带
SessionID,服务器通过内存或数据库验证用户身份。
- 用户登录后,服务器在内存中创建会话,并生成唯一的
-
数据存储:
- 用户状态数据存储在服务器的内存或外部存储(如 Redis)中。
-
示意图:
客户端 <--发送用户名密码--> 服务器<-- 生成SessionID 返回给客户端 -->
客户端 <--请求携带SessionID--> 服务器验证会话
1.2 sessionid 的结构与原理
SessionID 是服务端基于用户请求生成的唯一标识,通常保存在用户浏览器的 Cookie 中。它与服务端的存储(如内存、数据库或分布式缓存)绑定,用于记录用户的会话状态。
- 客户端发起登录请求,服务端生成 SessionID 并保存用户状态。
- SessionID 通过 Cookie 返回客户端,后续请求将附带该 Cookie,服务端校验并处理请求。
1.3 JWT
-
工作流程:
- 用户登录后,服务器生成一个加密签名的 JWT,包含用户信息和权限数据。
- JWT 返回给客户端,由客户端存储(通常存储在 Cookie 或 LocalStorage 中)。
- 客户端每次请求时携带 JWT,服务器解密验证其合法性,无需存储用户状态。
-
数据存储:
- 用户状态数据编码在 JWT 本身中,服务器无需额外存储。
-
JWT 结构:
- Header:描述算法和类型。
- Payload:存储用户信息和自定义数据。
- Signature:对 Header 和 Payload 的签名。
-
示意图:
客户端 <--发送用户名密码--> 服务器<-- 返回JWT令牌 -->
客户端 <--请求携带JWT--> 服务器验证签名
1.4 jwt 的结构与原理
JWT 是一种开放标准(RFC 7519),用于在各方之间以紧凑且安全的方式传递信息。其结构由三部分组成:Header、Payload 和 Signature。
1. Header(头部)
描述 Token 使用的算法和类型,例如:
{"alg": "HS256", // 签名算法,如 HMAC SHA-256"typ": "JWT" // Token 类型
}
2. Payload(载荷)
包含用户信息和其他声明(Claims),如:
{"sub": "1234567890", // 用户 ID"name": "John Doe", // 用户名"iat": 1516239022 // 签发时间(Unix 时间戳)
}
3. Signature(签名)
用来校验 Token 的完整性。通过以下公式生成:
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload),secret
)
3. jwt 与 sessionid 的区别
| 特性 | JWT | SessionID |
|---|---|---|
| 存储位置 | 客户端(本地存储或 Cookie) | 服务端(Session 存储 + 客户端 Cookie) |
| 状态管理 | 无状态(Stateless) | 有状态(Stateful) |
| 扩展性 | 高(跨域、跨服务) | 较低(需服务端集中管理) |
| 性能 | 快速,无需服务端存储,但签名验证耗时 | 需查询服务端状态,但无需验证签名 |
| 安全性 | 有潜在安全风险(如泄露或重放攻击) | 更安全,但易受 Session 固化攻击 |
| 适用场景 | 微服务、跨域登录 | 单体应用、状态复杂的长会话 |
4. jwt 与 sessionid 的应用场景
4.1 JWT 的应用场景
- 微服务架构:通过无状态的 Token,避免服务间的状态同步。
- 移动端或前后端分离项目:减少服务端负载,提升响应速度。
- 单点登录(SSO):允许跨域认证和用户会话共享。
4.2 SessionID 的应用场景
- 状态复杂的系统:需要服务端管理用户状态(如购物车、游戏状态)。
- 高安全性需求:如金融系统,通过服务端记录会话来防范滥用。
5. jwt 的优缺点
5.1 优点
- 无状态:服务端无需存储用户会话信息。
- 跨域支持:适合分布式应用。
- 高性能:客户端自持 Token,减少服务端访问压力。
5.2 缺点
- 安全性依赖签名机制,泄露后风险较大。
- Token 长度较长,可能增加带宽开销。
- 无法即时撤销,需额外实现黑名单机制。
6. 安全实践
JWT 的灵活性和高效性使其在现代应用中广受欢迎,但同时它也带来了安全风险。如果使用不当,可能会导致数据泄露或身份被冒用。以下是一些实用的安全实践,并结合示例说明。
6.1 短期有效期 + 刷新机制
将 JWT 的过期时间设置得尽量短(如 15 分钟),确保即使 Token 被泄露,攻击者也难以长期利用。为用户提供刷新机制,在 Token 即将过期时生成新 Token。
示例:设置短期有效期
// 生成 Token 时设置过期时间
Date now = new Date();
Date expiryDate = new Date(now.getTime() + 15 * 60 * 1000); // 15 分钟String token = Jwts.builder().setSubject(userId).setIssuedAt(now).setExpiration(expiryDate) // 设置过期时间.signWith(SignatureAlgorithm.HS256, SECRET_KEY) // 使用密钥签名.compact();
实现刷新机制
// 检查 Token 是否即将过期
if (token即将过期) {// 生成新的 TokenString newToken = generateToken(userId);// 返回新的 Token 给客户端response.addHeader("Authorization", "Bearer " + newToken);
}
6.2 敏感信息加密存储
JWT 的 Payload 可被解码,不能直接存储敏感信息。对于高度敏感的数据,如用户密码、交易信息,应加密存储或避免放入 JWT 中。
示例:AES 加密敏感信息
// 加密敏感信息
String sensitiveData = "userSecretInfo";
Cipher cipher = Cipher.getInstance("AES");
SecretKeySpec key = new SecretKeySpec(AES_KEY.getBytes(), "AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
String encryptedData = Base64.getEncoder().encodeToString(cipher.doFinal(sensitiveData.getBytes()));// 将加密信息存入 JWT 的 Payload
String token = Jwts.builder().claim("data", encryptedData) // 存入加密后的数据.signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();
解密敏感信息
// 从 Token 中解密敏感信息
String encryptedData = claims.get("data", String.class);
cipher.init(Cipher.DECRYPT_MODE, key);
String sensitiveData = new String(cipher.doFinal(Base64.getDecoder().decode(encryptedData)));
6.3 使用 HTTPS 保护传输安全
JWT 在网络中传输时可能被中间人攻击拦截。通过 HTTPS 加密传输可以确保 Token 在网络层的安全性。
- 确保所有服务均启用 HTTPS。
- 在 Web 应用中配置 HTTP Strict Transport Security(HSTS)头,强制客户端使用 HTTPS。
示例:Spring Boot 配置 HTTPS
server:ssl:enabled: truekey-store: classpath:keystore.p12key-store-password: your-passwordkey-store-type: PKCS12
6.4 签名验证
确保服务器验证每个请求的 JWT 签名,避免伪造 Token 的攻击。
示例:验证签名
try {Claims claims = Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody(); // 解析并验证 TokenString userId = claims.getSubject(); // 获取用户信息
} catch (JwtException e) {throw new SecurityException("Invalid Token");
}
6.5 实现黑名单机制
如果某个 Token 被识别为非法(如用户登出或检测到异常行为),需要立即撤销该 Token。由于 JWT 无状态,需通过黑名单机制记录失效的 Token。
示例:Redis 存储黑名单
// 将失效的 Token 存入 Redis
redisTemplate.opsForValue().set("blacklist:" + token, true, expiryTime, TimeUnit.MILLISECONDS);// 检查请求中的 Token 是否在黑名单中
if (redisTemplate.hasKey("blacklist:" + token)) {throw new SecurityException("Token is invalid");
}
6.6 防范重放攻击
攻击者可能截获用户的合法请求并重复使用。通过以下方法防范:
- 添加随机标识(Nonce):确保每个请求唯一。
- 时间戳校验:Token 使用时间戳限制,过期即失效。
示例:使用时间戳校验
// Token 中增加时间戳字段
String token = Jwts.builder().claim("timestamp", System.currentTimeMillis()).signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();// 校验时间戳是否合理
long timestamp = claims.get("timestamp", Long.class);
if (System.currentTimeMillis() - timestamp > MAX_ALLOWED_DRIFT) {throw new SecurityException("Replay attack detected");
}
6.7 使用更安全的算法
尽量避免使用对称加密算法(如 HS256),而是采用非对称加密算法(如 RS256)。这样,服务器可以使用私钥签名,客户端用公钥验证,进一步提升安全性。
示例:RS256 签名与验证
// 签名
String token = Jwts.builder().setSubject(userId).signWith(privateKey, SignatureAlgorithm.RS256).compact();// 验证
Claims claims = Jwts.parserBuilder().setSigningKey(publicKey).build().parseClaimsJws(token).getBody();
6.8 限制 Token 权限与作用范围
通过字段限制 Token 的权限和适用场景,防止滥用。例如:
- aud(Audience):指定 Token 仅用于特定 API。
- scope:限制操作范围(如只允许读取数据)。
示例:设置权限字段
String token = Jwts.builder().claim("scope", "read").signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();// 校验 Token 是否有足够权限
if (!"read".equals(claims.get("scope", String.class))) {throw new SecurityException("Insufficient permissions");
}
通过上述安全实践,我们可以显著提升 JWT 的使用安全性,从而在保障性能的同时,减少潜在的安全风险。
7. 总结
JWT 和 SessionID 各有优势,具体选择需根据应用场景而定:
- 无状态需求:优先考虑 JWT。
- 安全性和灵活性:SessionID 是更好的选择。
在实际项目中,可以结合两者的优点。例如:
- 使用 JWT 处理微服务中的用户认证。
- 在服务端为 JWT 增加会话状态记录,提升安全性。
通过合理配置和优化,JWT 和 SessionID 都能满足现代 Web 应用的认证需求。
相关文章:
jwt 与 sessionid 的区别及应用场景
在现代 Web 应用中,JWT(JSON Web Token)和SessionID是两种常用的用户认证和状态管理机制。本文从两者的原理、区别、优缺点以及适用场景展开分析,结合常见问题提出了最佳实践建议,帮助开发者更好地选择和使用。 JWT与S…...
tomcat和nginx
Tomcat 和 Nginx 都可以部署 Web 应用,但它们的核心功能和适用场景不同,因此在 2024 年生产环境及未来,是否使用 Tomcat 取决于需求和技术架构的特点。 1. Tomcat 的特点与适用场景 Tomcat 是 Java Servlet 容器,主要用来运行基于…...
服务器带宽与数据安全的重要性与作用
服务器带宽指的是服务器与外部网络通信的能力,即服务器发送和接收数据的速率。带宽越大,服务器在同一时间内能够处理的数据量就越多,数据传输的速度和稳定性也就越高。在数字化时代,企业对于数据的依赖程度日益加深,无…...
JSON数据处理
1. JSON注解 Data NoArgsConstructor AllArgsConstructor JsonIgnoreProperties(ignoreUnknowntrue) JSON注解: JsonIgnoreProperties(ignoreUnknowntrue) Hutool 日期格式化: DatePattern DateTimeFormat(pattern "yyyy-MM-dd HH:mm:ss")…...
FSWIND脉动风-风载时程生成器软件原理
大量风的实测资料表明,在风的时程曲线中,瞬时风速包含两个部分:一部分是自振周期一般在 10 分钟以上的平均风,另一部分是周期一般只有几秒左右的脉动风。平均风由于其周期一般比结构的自振周期大,因而考虑其作用性质相…...
搭建高可用负载均衡系统:Nginx 与云服务的最佳实践
搭建高可用负载均衡系统:Nginx 与云服务的最佳实践 引言 在项目开发过程中,我们通常在开发和测试阶段采用单机架构进行开发和测试。这是因为在这个阶段,系统的主要目的是功能实现和验证,单机架构足以满足开发人员的日常需求&…...
对比git命令与TortoiseGit工具,理解git解决冲突的过程
1 引言 此前用TortoiseSvn习惯了,所以,转到git时也同时选择了TortoiseGit工具。 同时,对比了可视化工具和git命令的操作,来深入理解git解决冲突的方式。 2 使用远程仓库替代本地仓库的内容 2.1 TortoiseGit做法 using “MERGE_…...
guava缓存的get方法的回调函数讲解一下
CacheBuilder.newBuilder()//设置缓存初始大小,应该合理设置,后续会扩容.initialCapacity(10)//最大值.maximumSize(100)//并发数设置.concurrencyLevel(5)//缓存过期时间,写入后10分钟过期.expireAfterWrite(600,TimeUnit.SECONDS)//统计缓存…...
React基础知识四 Hooks
什么是hooks? (coderwhy) hooks是react 16.8(2019年)出的新特性。 react有两种形式来创建组件——类式和函数式。在hooks之前类式组件就是react最主流的编程方式。 这个时候,函数式组件是非常鸡肋的,几乎没什么用。因…...
线性代数中的谱分解
一、谱分解的基本原理 谱分解(Spectral Decomposition)是线性代数中的一个重要概念,特别是在研究矩阵的特征值和特征向量时。它指的是将一个矩阵分解为其特征值和特征向量的组合,从而简化矩阵的运算和分析。谱分解通常适用于对称…...
Redis 数据结结构(一)—字符串、哈希表、列表
Redis(版本7.0)的数据结构主要包括字符串(String)、哈希表(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set)、超日志(…...
【Python】用Python和Paramiko实现远程服务器自动化管理
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 在现代IT环境中,远程服务器管理已成为运维工作的常态。随着自动化运维的需求不断增加,如何高效地管理远程服务器,提升操作的灵活性和效率…...
PDF处理的创新工具:福昕低代码平台尝鲜
在当今数字化时代,PDF文件的处理和管理变得越来越重要。福昕低代码平台是新发布的一款创新的工具,旨在简化PDF处理和管理的流程。通过这个平台,用户可以通过简单的拖拽界面上的按钮,轻松完成对Cloud API的调用工作流,而…...
openstack创建浮动IP全过程
1、创建外部网络,即是provider网络,有关provider网络的详细解释请参见我之前的文章openstack中的self-service和provider网络_openstack provider网络不能创建vlan吗-CSDN博客 network create --share --external --provider-physical-network physnet1…...
nginx漏洞修复
漏洞名称:web服务器http信息头公开 解决,在以下各个监听端口加上一行,然后重启****nginx server_tokens off; 漏洞名称:默认的nginx http服务器设置 解决:请求头加上以下参数 add_header Content-Security-Policy “…...
Jackson - 序列化时更改字段名称
在这个简短的教程中,我将向您展示如何在序列化时更改字段名称以映射到另一个JSON属性。 Jackson库提供了JsonProperty注解,用于改变序列化JSON中的属性名称。 依赖项 首先,在pom.xml文件中添加以下依赖项: <dependency>…...
策略模式实战 - 猜拳游戏
**可以整体的替换一套算法,这就是策略模式。**这样对于同一个问题,可以有多种解决方案——算法实现的时候,可以通过策略模式来非常方便的进行算法的整体替换,而各种算法是独立封装好的,不用修改其内部逻辑。 具体的实…...
AWS ECS Task 添加 Prometheus 监控采集配置详细指南
以下是一篇完整的博文,介绍如何在 AWS ECS 环境中实现 JVM 监控。 AWS ECS 环境下的 JVM 监控实践 概述 在 AWS ECS (Elastic Container Service) 环境中监控 Java 应用性能是一项重要任务。本文将详细介绍如何使用 AWS Distro for OpenTelemetry (ADOT) 结合 Spring Boot …...
5. 一分钟读懂“工厂方法模式”
5.1 模式介绍 你可能会发现,简单工厂模式没在经典设计模式里出现,别急,它其实只是个常用的编程技巧,而不是标准的设计模式。简单工厂模式有三个要素:1个产品接口、n个产品类、1个工厂类,工厂类通过if/else来…...
基于 AutoFlow 快速搭建基于 TiDB 向量搜索的本地知识库问答机器人
导读 本文将详细介绍如何通过 PingCAP 开源项目 AutoFlow 实现快速搭建基于 TiDB 的本地知识库问答机器人。如果提前准备好 Docker、TiDB 环境,整个搭建过程估计在 10 分钟左右即可完成,无须开发任何代码。 文中使用一篇 TiDB 文档作为本地数据源作为示…...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容
基于 UniApp + WebSocket实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...
React Native在HarmonyOS 5.0阅读类应用开发中的实践
一、技术选型背景 随着HarmonyOS 5.0对Web兼容层的增强,React Native作为跨平台框架可通过重新编译ArkTS组件实现85%以上的代码复用率。阅读类应用具有UI复杂度低、数据流清晰的特点。 二、核心实现方案 1. 环境配置 (1)使用React Native…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
