当前位置: 首页 > news >正文

jwt 与 sessionid 的区别及应用场景

在现代 Web 应用中,JWT(JSON Web Token)SessionID是两种常用的用户认证和状态管理机制。本文从两者的原理区别优缺点以及适用场景展开分析,结合常见问题提出了最佳实践建议,帮助开发者更好地选择和使用。


JWT与SessionID的区别及应用场景详解

在现代web应用开发中,JWT(JSON Web Token)SessionID是两种常用的身份验证机制。本文将从原理应用场景优缺点等角度深入剖析二者,帮助开发者在实际项目中做出合适的选择。


1. 原理解析

1.1 SessionID

  • 工作流程

    1. 用户登录后,服务器在内存中创建会话,并生成唯一的 SessionID
    2. SessionID 返回给客户端(通常通过 Cookie 存储)。
    3. 客户端每次请求时,携带 SessionID,服务器通过内存或数据库验证用户身份。
  • 数据存储

    • 用户状态数据存储在服务器的内存或外部存储(如 Redis)中。
  • 示意图

客户端  <--发送用户名密码-->  服务器<-- 生成SessionID 返回给客户端 -->
客户端  <--请求携带SessionID-->  服务器验证会话

1.2 sessionid 的结构与原理

SessionID 是服务端基于用户请求生成的唯一标识,通常保存在用户浏览器的 Cookie 中。它与服务端的存储(如内存、数据库或分布式缓存)绑定,用于记录用户的会话状态。

  • 客户端发起登录请求,服务端生成 SessionID 并保存用户状态。
  • SessionID 通过 Cookie 返回客户端,后续请求将附带该 Cookie,服务端校验并处理请求。

1.3 JWT

  • 工作流程

    1. 用户登录后,服务器生成一个加密签名的 JWT,包含用户信息和权限数据。
    2. JWT 返回给客户端,由客户端存储(通常存储在 Cookie 或 LocalStorage 中)。
    3. 客户端每次请求时携带 JWT,服务器解密验证其合法性,无需存储用户状态。
  • 数据存储

    • 用户状态数据编码在 JWT 本身中,服务器无需额外存储。
  • JWT 结构

    • Header:描述算法和类型。
    • Payload:存储用户信息和自定义数据。
    • Signature:对 Header 和 Payload 的签名。
  • 示意图

客户端  <--发送用户名密码-->  服务器<-- 返回JWT令牌 -->
客户端  <--请求携带JWT-->  服务器验证签名

1.4 jwt 的结构与原理

JWT 是一种开放标准(RFC 7519),用于在各方之间以紧凑且安全的方式传递信息。其结构由三部分组成:HeaderPayloadSignature

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 的区别
特性JWTSessionID
存储位置客户端(本地存储或 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 防范重放攻击

攻击者可能截获用户的合法请求并重复使用。通过以下方法防范:

  1. 添加随机标识(Nonce):确保每个请求唯一。
  2. 时间戳校验: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 应用中&#xff0c;JWT&#xff08;JSON Web Token&#xff09;和SessionID是两种常用的用户认证和状态管理机制。本文从两者的原理、区别、优缺点以及适用场景展开分析&#xff0c;结合常见问题提出了最佳实践建议&#xff0c;帮助开发者更好地选择和使用。 JWT与S…...

tomcat和nginx

Tomcat 和 Nginx 都可以部署 Web 应用&#xff0c;但它们的核心功能和适用场景不同&#xff0c;因此在 2024 年生产环境及未来&#xff0c;是否使用 Tomcat 取决于需求和技术架构的特点。 1. Tomcat 的特点与适用场景 Tomcat 是 Java Servlet 容器&#xff0c;主要用来运行基于…...

服务器带宽与数据安全的重要性与作用

服务器带宽指的是服务器与外部网络通信的能力&#xff0c;即服务器发送和接收数据的速率。带宽越大&#xff0c;服务器在同一时间内能够处理的数据量就越多&#xff0c;数据传输的速度和稳定性也就越高。在数字化时代&#xff0c;企业对于数据的依赖程度日益加深&#xff0c;无…...

JSON数据处理

1. JSON注解 Data NoArgsConstructor AllArgsConstructor JsonIgnoreProperties(ignoreUnknowntrue) JSON注解&#xff1a; JsonIgnoreProperties(ignoreUnknowntrue) Hutool 日期格式化&#xff1a; DatePattern DateTimeFormat(pattern "yyyy-MM-dd HH:mm:ss")…...

FSWIND脉动风-风载时程生成器软件原理

大量风的实测资料表明&#xff0c;在风的时程曲线中&#xff0c;瞬时风速包含两个部分&#xff1a;一部分是自振周期一般在 10 分钟以上的平均风&#xff0c;另一部分是周期一般只有几秒左右的脉动风。平均风由于其周期一般比结构的自振周期大&#xff0c;因而考虑其作用性质相…...

搭建高可用负载均衡系统:Nginx 与云服务的最佳实践

搭建高可用负载均衡系统&#xff1a;Nginx 与云服务的最佳实践 引言 在项目开发过程中&#xff0c;我们通常在开发和测试阶段采用单机架构进行开发和测试。这是因为在这个阶段&#xff0c;系统的主要目的是功能实现和验证&#xff0c;单机架构足以满足开发人员的日常需求&…...

对比git命令与TortoiseGit工具,理解git解决冲突的过程

1 引言 此前用TortoiseSvn习惯了&#xff0c;所以&#xff0c;转到git时也同时选择了TortoiseGit工具。 同时&#xff0c;对比了可视化工具和git命令的操作&#xff0c;来深入理解git解决冲突的方式。 2 使用远程仓库替代本地仓库的内容 2.1 TortoiseGit做法 using “MERGE_…...

guava缓存的get方法的回调函数讲解一下

CacheBuilder.newBuilder()//设置缓存初始大小&#xff0c;应该合理设置&#xff0c;后续会扩容.initialCapacity(10)//最大值.maximumSize(100)//并发数设置.concurrencyLevel(5)//缓存过期时间&#xff0c;写入后10分钟过期.expireAfterWrite(600,TimeUnit.SECONDS)//统计缓存…...

React基础知识四 Hooks

什么是hooks&#xff1f; (coderwhy) hooks是react 16.8&#xff08;2019年&#xff09;出的新特性。 react有两种形式来创建组件——类式和函数式。在hooks之前类式组件就是react最主流的编程方式。 这个时候&#xff0c;函数式组件是非常鸡肋的&#xff0c;几乎没什么用。因…...

线性代数中的谱分解

一、谱分解的基本原理 谱分解&#xff08;Spectral Decomposition&#xff09;是线性代数中的一个重要概念&#xff0c;特别是在研究矩阵的特征值和特征向量时。它指的是将一个矩阵分解为其特征值和特征向量的组合&#xff0c;从而简化矩阵的运算和分析。谱分解通常适用于对称…...

Redis 数据结结构(一)—字符串、哈希表、列表

Redis&#xff08;版本7.0&#xff09;的数据结构主要包括字符串&#xff08;String&#xff09;、哈希表&#xff08;Hash&#xff09;、列表&#xff08;List&#xff09;、集合&#xff08;Set&#xff09;、有序集合&#xff08;Sorted Set&#xff09;、超日志&#xff08…...

【Python】用Python和Paramiko实现远程服务器自动化管理

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 在现代IT环境中,远程服务器管理已成为运维工作的常态。随着自动化运维的需求不断增加,如何高效地管理远程服务器,提升操作的灵活性和效率…...

PDF处理的创新工具:福昕低代码平台尝鲜

在当今数字化时代&#xff0c;PDF文件的处理和管理变得越来越重要。福昕低代码平台是新发布的一款创新的工具&#xff0c;旨在简化PDF处理和管理的流程。通过这个平台&#xff0c;用户可以通过简单的拖拽界面上的按钮&#xff0c;轻松完成对Cloud API的调用工作流&#xff0c;而…...

openstack创建浮动IP全过程

1、创建外部网络&#xff0c;即是provider网络&#xff0c;有关provider网络的详细解释请参见我之前的文章openstack中的self-service和provider网络_openstack provider网络不能创建vlan吗-CSDN博客 network create --share --external --provider-physical-network physnet1…...

nginx漏洞修复

漏洞名称&#xff1a;web服务器http信息头公开 解决&#xff0c;在以下各个监听端口加上一行&#xff0c;然后重启****nginx server_tokens off; 漏洞名称&#xff1a;默认的nginx http服务器设置 解决&#xff1a;请求头加上以下参数 add_header Content-Security-Policy “…...

Jackson - 序列化时更改字段名称

在这个简短的教程中&#xff0c;我将向您展示如何在序列化时更改字段名称以映射到另一个JSON属性。 Jackson库提供了JsonProperty注解&#xff0c;用于改变序列化JSON中的属性名称。 依赖项 首先&#xff0c;在pom.xml文件中添加以下依赖项&#xff1a; <dependency>…...

策略模式实战 - 猜拳游戏

**可以整体的替换一套算法&#xff0c;这就是策略模式。**这样对于同一个问题&#xff0c;可以有多种解决方案——算法实现的时候&#xff0c;可以通过策略模式来非常方便的进行算法的整体替换&#xff0c;而各种算法是独立封装好的&#xff0c;不用修改其内部逻辑。 具体的实…...

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 模式介绍 你可能会发现&#xff0c;简单工厂模式没在经典设计模式里出现&#xff0c;别急&#xff0c;它其实只是个常用的编程技巧&#xff0c;而不是标准的设计模式。简单工厂模式有三个要素&#xff1a;1个产品接口、n个产品类、1个工厂类&#xff0c;工厂类通过if/else来…...

基于 AutoFlow 快速搭建基于 TiDB 向量搜索的本地知识库问答机器人

导读 本文将详细介绍如何通过 PingCAP 开源项目 AutoFlow 实现快速搭建基于 TiDB 的本地知识库问答机器人。如果提前准备好 Docker、TiDB 环境&#xff0c;整个搭建过程估计在 10 分钟左右即可完成&#xff0c;无须开发任何代码。 文中使用一篇 TiDB 文档作为本地数据源作为示…...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

08. C#入门系列【类的基本概念】:开启编程世界的奇妙冒险

C#入门系列【类的基本概念】&#xff1a;开启编程世界的奇妙冒险 嘿&#xff0c;各位编程小白探险家&#xff01;欢迎来到 C# 的奇幻大陆&#xff01;今天咱们要深入探索这片大陆上至关重要的 “建筑”—— 类&#xff01;别害怕&#xff0c;跟着我&#xff0c;保准让你轻松搞…...

【Linux系统】Linux环境变量:系统配置的隐形指挥官

。# Linux系列 文章目录 前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变量的生命周期 四、环境变量的组织方式五、C语言对环境变量的操作5.1 设置环境变量&#xff1a;setenv5.2 删除环境变量:unsetenv5.3 遍历所有环境…...

关于easyexcel动态下拉选问题处理

前些日子突然碰到一个问题&#xff0c;说是客户的导入文件模版想支持部分导入内容的下拉选&#xff0c;于是我就找了easyexcel官网寻找解决方案&#xff0c;并没有找到合适的方案&#xff0c;没办法只能自己动手并分享出来&#xff0c;针对Java生成Excel下拉菜单时因选项过多导…...

tauri项目,如何在rust端读取电脑环境变量

如果想在前端通过调用来获取环境变量的值&#xff0c;可以通过标准的依赖&#xff1a; std::env::var(name).ok() 想在前端通过调用来获取&#xff0c;可以写一个command函数&#xff1a; #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...

【Veristand】Veristand环境安装教程-Linux RT / Windows

首先声明&#xff0c;此教程是针对Simulink编译模型并导入Veristand中编写的&#xff0c;同时需要注意的是老用户编译可能用的是Veristand Model Framework&#xff0c;那个是历史版本&#xff0c;且NI不会再维护&#xff0c;新版本编译支持为VeriStand Model Generation Suppo…...

【Linux】Linux安装并配置RabbitMQ

目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的&#xff0c;需要先安…...

Linux 下 DMA 内存映射浅析

序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存&#xff0c;但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程&#xff0c;可以参考这篇文章&#xff0c;我觉得写的非常…...