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

JWT概念及使用详解

核心概念:JWT是什么?

JWT,全称是 JSON Web Token,是一种开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间作为JSON对象安全地传输信息。

你可以把它想象成一个数字身份证安全通行证。当用户登录成功后,服务器会生成一个JWT并返回给客户端(通常是浏览器)。客户端在后续的请求中都需要带着这个“通行证”,服务器通过验证这个通行证来确认用户的身份和权限。


为什么在Java项目中使用JWT?(主要为了解决什么问题?)

在传统的Web应用中,我们使用 Session 机制来保持用户的登录状态。但Session有一些局限性,尤其是在现代分布式、微服务架构中:

  1. 服务器内存开销:每个用户的Session信息都存储在服务器内存中,用户量巨大时对服务器压力很大。

  2. 扩展性问题:当你有多台服务器(集群)时,需要做Session共享(Session Replication)或使用外部存储(如Redis),增加了架构的复杂性。

  3. 不适合跨域:在前后端分离、跨域API调用(如手机APP访问后端API)的场景下,基于Cookie的Session机制用起来很麻烦。

JWT的出现完美地解决了这些问题:

  • 无状态(Stateless):服务器不需要存储任何用户状态。用户的全部认证信息都存储在JWT本身中,并由客户端携带。这使得服务器应用非常容易扩展。

  • 跨域友好:可以轻松通过HTTP Header(通常是 Authorization: Bearer <token>)进行传输,完美支持跨域请求和移动端。

  • 自包含(Self-contained):Payload部分可以包含用户ID、角色等所有需要的信息,减少多次查询数据库的需要。


JWT的组成结构

一个JWT通常看起来像这样(由三部分组成,用点.分隔):
xxxxx.yyyyy.zzzzz

例如:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

  1. Header(头部)

    • 通常由两部分组成:令牌的类型(即"JWT")和所使用的签名算法(如HMAC SHA256或RSA)。

    • 这是一个JSON对象经过 Base64Url 编码后形成的字符串。

    • 示例解码后:{"alg": "HS256", "typ": "JWT"}

  2. Payload(负载)

    • 包含了你要传递的“声明”(Claims)。声明是关于实体(通常是用户)和其他数据的陈述。

    • 有三种类型的声明:

      • 注册标准声明:预定义但不强制使用的标准字段,如 iss(签发者), exp(过期时间), sub(主题), aud(受众)等。

      • 公共声明:可以添加任何信息的自定义字段,但为了避免冲突,应在IANA JSON Web Token Registry中定义或使用抗冲突命名空间的名称。

      • 私有声明:自定义的字段,用于在同意使用它们的各方之间共享信息。

    • 同样是一个JSON对象经过 Base64Url 编码后形成的字符串。

    • 示例解码后:{"sub": "1234567890", "name": "John Doe", "iat": 1516239022}

  3. Signature(签名)

    • 这是最核心的部分,用于防止令牌被篡改。

    • 签名是通过将编码后的Header、编码后的Payload、一个密钥(Secret)以及Header中指定的算法生成。

    • 例如,使用HMAC SHA256算法的签名是这样创建的:

      java

      HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload),secret)

在Java项目中的典型工作流程

  1. 认证(Login):用户使用用户名密码登录。

  2. 生成JWT:服务器验证凭据有效后,根据用户信息(如userId, role)生成一个JWT,并使用一个只有服务器知道的密钥(Secret) 进行签名。然后将JWT返回给客户端(通常在响应体中)。

  3. 客户端存储:客户端(如浏览器)收到JWT后,通常会将其存储在本地(Local Storage, Session Storage或Cookie中)。

  4. 携带JWT访问:客户端在后续请求的HTTP Header中添加:Authorization: Bearer <JWT>

  5. 验证JWT:服务器接收到请求后,提取Header中的JWT:

    • 检查签名是否有效(使用相同的密钥和算法进行验证),确保令牌未被篡改。

    • 检查令牌是否过期(检查exp声明)。

    • 如果一切有效,就从Payload中解析出用户信息(如userId),并进行后续业务处理。

  6. 响应请求:服务器验证通过后,返回客户端请求的资源或数据。


常用的Java JWT库

在Java中,你不需要自己实现JWT的编码、解码和签名逻辑,可以使用成熟的开源库:

  • jjwt:一个非常流行、易于使用的库。

  • java-jwt:Auth0公司提供的库,功能强大。

  • Nimbus JOSE + JWT:一个更全面、功能更丰富的库。

示例(使用jjwt库生成一个JWT):

java

import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import java.security.Key;// 生成一个安全的密钥(生产环境中应从一个安全的配置文件中读取,而不是硬编码)
Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);// 构建JWT
String jws = Jwts.builder().setSubject("1234567890") // 设置主题(通常是用户ID).claim("name", "John Doe") // 添加自定义声明.claim("admin", true)      // 添加自定义声明.setIssuedAt(new Date())   // 设置签发时间.setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 设置过期时间(1小时后).signWith(key)             // 使用密钥签名.compact();                // 压缩生成最终的字符串System.out.println(jws);

注意事项

  • 安全存储密钥:签名密钥是安全的核心,必须妥善保管,绝不能泄露。

  • 不要在不安全的信道传输敏感信息:JWT的Payload只是Base64编码,并不是加密的(除非你使用了JWE)。绝对不要在JWT中存放密码等敏感信息

  • 管理Token过期:一定要为JWT设置合理的过期时间(exp),以减少令牌被盗用的风险。

  • 选择合适的存储方式:在浏览器端,存储在LocalStorage有XSS风险,存储在Cookie有CSRF风险,需要根据实际情况权衡并做好相应的安全防护。

总结来说,在Java项目中,JWT是一种用于实现无状态、可扩展的分布式用户认证和授权的令牌机制,它是构建现代API和微服务架构的基石之一。

http://www.xdnf.cn/news/20355.html

相关文章:

  • Dart语言基础 关键字 var与dynamic
  • 整车无线布置的综述
  • 【完整源码+数据集+部署教程】室内场景分割系统源码和数据集:改进yolo11-DWR
  • 算法题(200):最大子段和(动态规划)
  • 责任链框架 03:处理器实现
  • 《Science》神经炎症综述思路套用:从机制到跨领域研究范式
  • Python实现生成矩形框、三角形框、六边形框和圆环点云
  • 自动拆箱和装箱的原理与作用
  • HMI(人机界面)
  • 【基础-单选】UIAbility实例创建完成时触发的回调
  • HTML 列表类型
  • 5-8单元格区域与VS数组应用(实例:提取满足条件的数据)
  • Qt多线程编程学习
  • EG2103 SOP-8 内置600V功率MOS管 栅极驱动芯片
  • I/O 多路复用 (I/O Multiplexing)
  • 四个关于云属性的四个卫星数据集的介绍
  • 基于Spring Boot + Vue3的办公用品申领管理系统
  • 部署AIRI
  • lesson55:CSS导航组件全攻略:从基础导航条到动态三级菜单与伸缩菜单实现
  • 02.继承MonoBehaviour的单例模式基类
  • Python快速入门专业版(七):整数与浮点数:Python数值类型的运算与精度问题(附解决方案)
  • 项目中的一些比较实用的自定义控件
  • Python文件打包为EXE的工具v1.0
  • 《AI大模型应知应会100篇》第67篇 Web应用与大模型集成开发实践——1小时打造国产大模型智能客服系统
  • MySQL问题5
  • github上传步骤
  • 季度最强策略:年化247%,回撤10%,夏普比率3.79。附大小盘轮动策略python源代码。
  • Nestjs框架: 使用 CASL 库实现基于角色的权限控制(RBAC)与细粒度访问控制的实战演示
  • 【嵌入式C语言】七
  • 【IQA技术专题】 多尺度的transformer网络IQA:MUSIQ