news 2026/2/25 11:03:43

什么是 JWT?一文彻底搞懂 JSON Web Token(附 Spring Boot 实战)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
什么是 JWT?一文彻底搞懂 JSON Web Token(附 Spring Boot 实战)

视频看了几百小时还迷糊?关注我,几分钟让你秒懂!

你是否经常听到这些词:

  • “我们用 JWT 做登录认证”
  • “前端把 token 放在 Authorization 头里”
  • “JWT 无状态,适合分布式系统”

但你真的理解JWT 到底是什么?它怎么工作?和 Session 有什么区别?吗?

今天我们就用通俗语言 + 图解 + Spring Boot 代码实战,带你从零彻底搞懂 JWT!


🧩 一、一句话解释 JWT

JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在网络应用间安全地传递“声明”(claims)的紧凑、自包含令牌。

简单说:JWT 就是一个加密的字符串,里面包含了用户身份信息,服务器不用查数据库就能验证你是谁!


🔍 二、JWT 长什么样?

一个典型的 JWT 看起来像这样:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ. SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

它由三部分组成,用点.分隔

部分说明是否可读
Header(头部)算法 + 类型Base64 可解码
Payload(载荷)用户数据(如 ID、角色、过期时间)Base64 可解码
Signature(签名)用于验证令牌是否被篡改不可逆

注意:JWT 默认是 Base64 编码,不是加密!任何人都能解码看到内容!
🔒 安全靠的是签名(Signature),防止内容被篡改。


📦 三、三部分详解(附解码示例)

1. Header(头部)

{ "alg": "HS256", "typ": "JWT" }
  • alg:签名算法(如 HS25 sH A256、RS256)
  • typ:令牌类型,固定为 JWT

2. Payload(载荷)— 存放用户信息的地方!

{ "sub": "1234567890", // 主题(通常是用户ID) "name": "John Doe", "admin": true, "iat": 1516239022, // 签发时间(时间戳) "exp": 1516242622 // 过期时间(重要!) }

⚠️不要在 Payload 里放敏感信息(如密码、手机号)!因为它是明文(Base64 可解码)!

3. Signature(签名)— 安全的核心!

服务器用密钥 + 算法Header + Payload进行签名:

HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secretKey )
  • 客户端无法伪造签名(不知道 secretKey);
  • 服务器收到 JWT 后,会重新计算签名,比对是否一致;
  • 只要 Payload 被改,签名就失效!

🔄 四、JWT 认证流程(图解)

✅ 整个过程服务器无需存储 session,真正“无状态”!


⚖️ 五、JWT vs Session(传统方案)

特性JWTSession
存储位置客户端(LocalStorage/Cookie)服务端(内存/Redis)
状态无状态(Stateless)有状态(需维护 session)
扩展性天然支持分布式需共享 session(如 Redis)
安全性依赖签名,防篡改依赖 session ID 随机性
登出难(需黑名单或短期过期)容易(删 session 即可)
传输大小较大(含用户数据)小(只传 session ID)

💡JWT 适合:API 服务、微服务、移动端
💡Session 适合:传统 Web 应用、需要强登出控制的系统


💻 六、Spring Boot 实战:手写 JWT 登录

1. 添加依赖

<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>0.11.5</version> </attribute> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-impl</artifactId> <version>0.11.5</version> <scope>runtime</scope> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-jackson</artifactId> <version>0.11.5</version> <scope>runtime</scope> </dependency>

2. JWT 工具类

@Component public class JwtUtil { private String secret = "MySecretKey123!@#"; // 生产环境应配置在 application.yml private long expiration = 86400000; // 24小时 public String generateToken(String userId) { return Jwts.builder() .setSubject(userId) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + expiration)) .signWith(SignatureAlgorithm.HS256, secret) .compact(); } public String getUserIdFromToken(String token) { return Jwts.parser() .setSigningKey(secret) .parseClaimsJws(token) .getBody() .getSubject(); } public boolean validateToken(String token) { try { Jwts.parser().setSigningKey(secret).parseClaimsJws(token); return true; } catch (Exception e) { return false; } } }

3. 登录接口

@RestController public class AuthController { @Autowired private JwtUtil jwtUtil; @PostMapping("/login") public ResponseEntity<?> login(@RequestBody LoginRequest req) { // 模拟验证账号密码(实际应查数据库) if ("admin".equals(req.getUsername()) && "123456".equals(req.getPassword())) { String token = jwtUtil.generateToken("10001"); return ResponseEntity.ok(Map.of("token", token)); } return ResponseEntity.status(401).body("账号或密码错误"); } }

4. 拦截器:验证 JWT

public class JwtInterceptor implements HandlerInterceptor { @Autowired private JwtUtil jwtUtil; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { String authHeader = request.getHeader("Authorization"); if (authHeader != null && authHeader.startsWith("Bearer ")) { String token = authHeader.substring(7); if (jwtUtil.validateToken(token)) { // 可将用户ID存入 ThreadLocal 或 Request Attribute return true; } } response.setStatus(401); return false; } }

注册拦截器:

@Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new JwtInterceptor()) .addPathPatterns("/api/**") .excludePathPatterns("/login"); } }

⚠️ 七、JWT 的致命缺点 & 注意事项

❌ 1.无法主动登出(除非用黑名单)

  • JWT 一旦签发,在过期前一直有效;
  • 即使用户点击“退出”,旧 token 仍可使用;
  • 解决方案
    • 设置较短过期时间(如 15 分钟)+ 刷新令牌(Refresh Token);
    • 维护一个 Redis 黑名单,记录已登出的 token。

❌ 2.Payload 不是加密的!

  • 所有人都能解码看到内容;
  • 永远不要放密码、身份证号等敏感信息!

❌ 3.密钥泄露 = 全盘崩溃

  • 如果secretKey泄露,攻击者可伪造任意用户 token;
  • 必须严格保管密钥!

✅ 最佳实践建议:

项目建议
过期时间Access Token 15~30 分钟,配合 Refresh Token
存储位置Web 用 HttpOnly Cookie(防 XSS),App 用安全存储
传输协议必须 HTTPS
密钥管理用配置中心或环境变量,不要硬编码

🎯 总结

  • JWT = Header + Payload + Signature
  • 自包含、无状态、适合分布式
  • 不是加密,而是签名防篡改
  • 无法主动登出是最大短板
  • Spring Boot 集成简单,但要注意安全细节

掌握 JWT,你就掌握了现代 API 认证的“通行证”!


视频看了几百小时还迷糊?关注我,几分钟让你秒懂!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/19 22:22:55

NSCAT 2 级海洋风矢量地球物理数据记录

NSCAT Level 2 Ocean Wind Vector Geophysical Data Record 简介 美国国家航空航天局散射计&#xff08;NSCAT&#xff09;二级海洋风矢量数据以 50 公里风矢量网格&#xff08;WVC&#xff09;幅宽呈现&#xff0c;包含每日上升和下降轨道的数据。风矢量的精度在 2 米/秒&am…

作者头像 李华
网站建设 2026/2/19 15:32:12

【Android毕设全套源码+文档】基于微信小程序的医院医疗设备管理系统的设计与实现(丰富项目+远程调试+讲解+定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/2/24 12:29:04

【Android毕设全套源码+文档】基于AndroidSSM框架的志愿者服务平台的设计与实现(丰富项目+远程调试+讲解+定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/2/15 16:58:58

Git分支管理全面指南:从基础操作到Gerrit高级实践

引言 在现代软件开发中&#xff0c;高效的分支管理是团队协作的基石。Git作为最流行的版本控制系统&#xff0c;配合Gerrit代码评审平台&#xff0c;形成了强大的代码质量管理体系。本文将深入探讨Git分支管理的各个方面&#xff0c;特别聚焦于Gerrit环境下的最佳实践&#xf…

作者头像 李华