跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava算法

JWT 详解:原理、流程与 Spring Boot 实战

综述由AI生成JWT 是一种用于在网络应用间安全传递声明的开放标准。它由 Header、Payload 和 Signature 三部分组成,通过签名防止篡改。相比 Session,JWT 无状态且适合分布式系统,但无法主动登出且 Payload 非加密。 JWT 原理、认证流程及与 Session 的区别,并通过 Spring Boot 实战演示了登录接口实现、拦截器配置及安全注意事项,如密钥管理和过期时间设置。

虚拟内存发布于 2026/4/6更新于 2026/5/2225 浏览

你是否经常听到这些词:

  • '我们用 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:签名算法(如 HS256、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>
</dependency>
<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 认证的'通行证'!

目录

  1. 🧩 一、一句话解释 JWT
  2. 🔍 二、JWT 长什么样?
  3. 📦 三、三部分详解(附解码示例)
  4. 1\. Header(头部)
  5. 2\. Payload(载荷)— 存放用户信息的地方!
  6. 3\. Signature(签名)— 安全的核心!
  7. 🔄 四、JWT 认证流程(图解)
  8. ⚖️ 五、JWT vs Session(传统方案)
  9. 💻 六、Spring Boot 实战:手写 JWT 登录
  10. 1\. 添加依赖
  11. 2\. JWT 工具类
  12. 3\. 登录接口
  13. 4\. 拦截器:验证 JWT
  14. ⚠️ 七、JWT 的致命缺点 & 注意事项
  15. ❌ 1. 无法主动登出(除非用黑名单)
  16. ❌ 2. Payload 不是加密的!
  17. ❌ 3. 密钥泄露 = 全盘崩溃
  18. ✅ 最佳实践建议:
  19. 🎯 总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • AI 生成图片提示词:新手入门指南与最佳实践
  • 人工智能时代:传统产品经理如何转型为 AI 产品经理
  • 2026 Python 展望:AI 时代的核心基础设施语言
  • FPGA 是什么?与 CPU/单片机的本质区别
  • Python 2026 发展局势:AI 时代的通用基础设施语言
  • 华为 HCIP-AI Solution Architect 核心技术考点与解析
  • 基于 AI 辅助开发的高并发在线考试系统实践
  • 前端内存泄漏排查与实战指南
  • 深入理解大模型预训练与微调:Pre-training 与 Fine-tuning 技术对比
  • 2026 年 Python 发展局势:AI 时代的通用基础设施语言
  • Spring Web MVC 核心原理与实战指南
  • 零基础转行 Python:从制造业到数据分析的实战经验与学习路径
  • AI 绘画 Face Fusion 人脸融合技巧与云端部署
  • Flutter 三方库 algolia_client_recommend 在鸿蒙端的适配实战
  • PMBus 电压监测精度提升:ADC 前端电路设计要点
  • 大模型开发转行指南:必备知识、技能与学习路径详解
  • AI 编程工具实战对比:Trae、Cursor、Copilot 与 Windsurf
  • 80 元低成本无人机系统设计与实现
  • DeepSeek-R1 大模型基于 MS-Swift 框架部署、推理与微调实战
  • 10 款主流开源后台管理系统推荐

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online