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

JWT 详解:原理、与 Session 区别及 Spring Boot 实战

综述由AI生成JWT 是一种用于在网络应用间安全传递声明的开放标准令牌。它由 Header、Payload 和 Signature 三部分组成,采用 Base64 编码而非加密,安全性依赖签名防篡改。相比 Session,JWT 无状态且适合分布式系统,但存在无法主动登出和 Payload 非加密的缺点。通过图解和 Spring Boot 代码实战,演示了 JWT 的生成、验证流程及拦截器配置,并提供了过期时间设置、密钥管理等最佳实践建议,帮助开发者安全集成 JWT 认证方案。

月亮邮递员发布于 2026/4/6更新于 2026/5/2226 浏览

JWT 详解:原理、对比与 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:签名算法(如 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 集成简单,但要注意安全细节

目录

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

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

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

更多推荐文章

查看全部
  • OpenClaw Skills 安装与实战:打造你的 AI 技能工具箱
  • Vitis 使用教程:从零实现 AI 模型 FPGA 部署
  • JavaScript 核心技术:XSLTProcessor 类型详解
  • 生物信息学入门核心技能:Linux、R 与 Python
  • Linux 进程核心解析:从 fork 开始理解程序运行
  • VSCode Copilot 网络无法连接的解决方法
  • C++ 手写日志模块:基于策略模式实现高性能日志系统
  • 使用 trae 集成安装 Claude Code 实践指南
  • ComfyUI Photoshop 插件安装与使用指南
  • 开源模型全景图:如何选择你的技术底座
  • TDD 实战:如何用测试驱动编写更优的 Python 代码
  • Xilinx Vivado 2020.1 安装流程与常见问题解析
  • Java 时间类(中):JDK8 全新时间 API 详解
  • 限流算法详解:令牌桶、漏桶与计数器算法及 Java 实现
  • HarmonyOS RcList 组件综合示例与尺寸计算
  • OpenClaw 接入 QQ 机器人配置指南
  • Rembg 图像去背服务独立部署与性能优化指南
  • C++ size_t 全面解析与深入拓展
  • 基于 SpringBoot+Vue 的酒店客房管理系统设计与实现
  • 四足机器人强化学习项目架构详解

相关免费在线工具

  • 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

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online