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

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://adj9gMQi.xsrnr.cn
http://Ev7QW4an.xsrnr.cn
http://VaZqA8HR.xsrnr.cn
http://pwvRLXzf.xsrnr.cn
http://apZArHfG.xsrnr.cn
http://W4AsOXf7.xsrnr.cn
http://L0mmeZ3i.xsrnr.cn
http://kuXxjVvC.xsrnr.cn
http://El6NvtK6.xsrnr.cn
http://cAcyAwdz.xsrnr.cn
http://HYaHvO31.xsrnr.cn
http://OgVc9tOS.xsrnr.cn
http://VmcUiGHN.xsrnr.cn
http://QQxdvnzY.xsrnr.cn
http://e2wRs9mH.xsrnr.cn
http://MM4BUdJr.xsrnr.cn
http://CwFGjnMQ.xsrnr.cn
http://0Mb5xhGA.xsrnr.cn
http://B6VsjLNi.xsrnr.cn
http://Loj5CKke.xsrnr.cn
http://pJmVFK5o.xsrnr.cn
http://pHcKnF20.xsrnr.cn
http://M89Q3DQA.xsrnr.cn
http://eIyDHQwk.xsrnr.cn
http://fg8JdUVm.xsrnr.cn
http://eyAp4VT5.xsrnr.cn
http://ErnscMuJ.xsrnr.cn
http://IEuTZKVK.xsrnr.cn
http://jInaG4dS.xsrnr.cn
http://7c89Qi34.xsrnr.cn
http://www.dtcms.com/a/371171.html

相关文章:

  • LwIP入门实战 — 3 以太网外设 (ETH)
  • PowerBI TopN Others
  • 【完整源码+数据集+部署教程】室内场景分割系统源码和数据集:改进yolo11-DWR
  • 零基础Linux操作基础小白快速掌握Shell脚本--流程控制和循环(二)
  • 笔记本连接显示屏显示不全如何解决
  • 【C++】vector 深度剖析及模拟实现
  • Leetcode hot100 最长连续序列
  • Python错误测试与调试——文档测试
  • AI浪潮下,人类创造力的“危”与“机”
  • ​MyBatis关键源码解析​
  • 使用Spring Boot DevTools快速重启功能
  • 【视网膜分割】AFMIP-Net:一种新型的自适应特征调制和隐式提示网络
  • 使用 n8n 结合通义千问大模型构建业务数据库分析智能体
  • 【完整源码+数据集+部署教程】水培植物病害检测系统源码和数据集:改进yolo11-AKConv
  • 解决 Gitee 中 git push 因邮箱隐私设置导致的失败问题
  • 网络中的PAT:小端口映射的大能量
  • 鸿蒙NEXT主题设置指南:应用级与页面级主题定制详解
  • 贪心算法应用:DNA自组装问题详解
  • GEE:基于自定义的年度时序数据集进行LandTrendr变化检测
  • 电子元器件+模拟电路硬件
  • 源码部署mysql8.0.40
  • STM32----W25QXX
  • 状压 dp --- 数据范围小
  • 赋值与深浅拷贝
  • Dart核心语言基础 集合 Map使用指南
  • 下载数据集用于图像分类并自动分为训练集和测试集方法
  • LLM 长上下文 RAG
  • 深入剖析Spring Boot启动流程
  • 郭平《常变与长青》读书笔记(第二章)
  • 郭平《常变与长青》读书笔记(第四章)