什么是 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 认证的“通行证”!


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

Read more

Z-Image-Turbo镜像推荐:Gradio WebUI免配置快速上手教程

Z-Image-Turbo镜像推荐:Gradio WebUI免配置快速上手教程 你是不是也遇到过这些情况:想试试最新的AI绘画模型,结果卡在环境搭建上——下载权重动辄几十GB、配置CUDA版本让人头大、改配置文件改到怀疑人生?或者好不容易跑起来了,WebUI界面又丑又难用,中文提示词还乱码?别折腾了。今天要介绍的这个镜像,真的做到了“点开即用”。 Z-Image-Turbo不是又一个参数堆砌的玩具模型,而是阿里通义实验室实打实打磨出来的高效文生图方案。它不靠堆显存换效果,而是用蒸馏技术把大模型的精华“浓缩”出来——8步出图、照片级质感、中英文文字渲染稳得一批,16GB显存的消费级显卡就能扛住。更重要的是,它被完整集成进了一个开箱即用的ZEEKLOG镜像里,连Gradio界面都给你调好了配色和字体,连“怎么输入中文”这种细节都考虑到了。 这篇文章不讲原理推导,不列参数表格,也不让你手动clone仓库、pip install一堆包。我们就用最直白的方式,带你从零开始,在5分钟内看到第一张由Z-Image-Turbo生成的高清图像。你不需要懂Diffusers,不需要会调acceler

【高级前端架构进阶】Nginx与Web 安全加固

【高级前端架构进阶】Nginx与Web 安全加固

🥅Nginx与Web 安全加固 🚪 引言 大家好!我是老曹,今天我们来聊聊Nginx的安全加固。在互联网这个"弱水三千"的世界里,我们的服务器就像一个"裸奔"的勇士,随时面临着各种安全威胁。🔥 Nginx 作为前端守护神,必须穿上"防弹衣"才能抵御恶意攻击。今天就让我们一起给Nginx来个"全副武装"! 🎯 学习目标 1. 🛡️ 掌握Nginx安全加固的基本概念和重要性 2. 🔍 理解server_tokens、ModSecurity插件、CSP设置的核心原理 3. 💻 学会配置各种安全策略来保护Web应用 4. 🚨 了解常见安全漏洞及防护措施 5. 📊 掌握安全配置的最佳实践 📋 核心知识点详解 ✅1. server_tokens 配置原理 🛡️ server_tokens 是Nginx的第一个安全防线,

WebToEpub完全指南:3步将网页小说变成精美EPUB电子书

WebToEpub完全指南:3步将网页小说变成精美EPUB电子书 【免费下载链接】WebToEpubA simple Chrome (and Firefox) Extension that converts Web Novels (and other web pages) into an EPUB. 项目地址: https://gitcode.com/gh_mirrors/we/WebToEpub 还在为网络小说无法离线阅读而烦恼吗?WebToEpub正是您需要的解决方案!这款免费浏览器扩展能够将任何网页内容快速转换为标准EPUB格式电子书,让您随时随地享受阅读乐趣。无论是连载小说、技术文档还是个人博客,WebToEpub都能轻松处理,真正实现"网页即电子书"的便捷体验。 🎯 为什么选择WebToEpub? 完全免费的本地处理 WebToEpub最大的优势在于完全免费且处理过程在本地进行。您的所有数据都不会上传到服务器,确保隐私安全。同时支持Chrome和Firefox两大主流浏览器,满足不同用户的使用习惯。 广泛的网站兼容性 内置数百个网站的专用解析器,涵盖主流轻小

前端微前端:别让你的应用变成巨石应用

前端微前端:别让你的应用变成巨石应用 毒舌时刻 这应用做得跟巨石似的,想改个功能都得动全身。 各位前端同行,咱们今天聊聊前端微前端。别告诉我你还在维护一个巨大的单体应用,那感觉就像在没有分区的大房子里生活——能住,但乱得要命。 为什么你需要微前端 最近看到一个项目,代码量超过 100 万行,构建时间超过 10 分钟,团队协作困难。我就想问:你是在做应用还是在做代码仓库? 反面教材 // 反面教材:单体应用 // App.jsx import React from 'react'; import Header from './components/Header'; import Sidebar from './components/Sidebar'; import Dashboard from