JWT的概念

JWT(JSON Web Token) 是一种开放标准(RFC 7519),用于在网络应用间安全地传输信息。它特别适用于 身份验证授权 场景。


🎯 JWT 的核心组成

JWT 由三部分组成,格式为:Header.Payload.Signature

1. Header(头部)

复制代码
{
  "alg": "HS256",  // 签名算法(HMAC SHA256)
  "typ": "JWT"     // 令牌类型
}
  • Base64Url 编码后形成第一部分

2. Payload(负载/声明)

包含实际的用户数据和其他信息:

复制代码
{
  "sub": "1234567890",       // 主题(用户ID)
  "name": "John Doe",        // 自定义声明
  "iat": 1516239022,         // 签发时间
  "exp": 1516242622          // 过期时间
}

3. Signature(签名)

复制代码
HMACSHA256(
  base64UrlEncode(header) + "." + 
  base64UrlEncode(payload),
  secret
)
  • 防止数据被篡改

📦 一个完整的 JWT 示例

复制代码
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.   // Header
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.   // Payload
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c   // Signature

JWT 在 Java 中的使用

常用 Java JWT 库

  1. jjwt(最流行)
  2. Java JWT (Auth0)
  3. Nimbus JWT

Maven 依赖(jjwt 示例)

复制代码
<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>

💻 Java 代码示例

1. 创建 JWT

复制代码
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;

public class JwtUtil {
    private static final String SECRET_KEY = "mySecretKey123!@#";
    private static final long EXPIRATION_TIME = 86400000; // 24小时
    
    public static String generateToken(String username) {
        return Jwts.builder()
            .setSubject(username)
            .setIssuedAt(new Date())
            .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
            .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
            .compact();
    }
}

2. 验证和解析 JWT

复制代码
public static boolean validateToken(String token) {
    try {
        Jwts.parser()
            .setSigningKey(SECRET_KEY)
            .parseClaimsJws(token);
        return true;
    } catch (Exception e) {
        return false;
    }
}

public static String getUsernameFromToken(String token) {
    return Jwts.parser()
        .setSigningKey(SECRET_KEY)
        .parseClaimsJws(token)
        .getBody()
        .getSubject();
}

🔐 JWT 在 Web 应用中的典型流程

复制代码
客户端 → 登录请求 → 服务器
          ↓
    验证用户名密码
          ↓
    生成JWT返回给客户端
          ↓
客户端 → 后续请求携带JWT(Authorization头)
          ↓
    服务器验证JWT
          ↓
    返回受保护资源

HTTP 请求头示例

复制代码
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

JWT 的优点

优点 说明
无状态 服务器不需要存储session,适合分布式系统
跨域友好 适合前后端分离、微服务架构
自包含 令牌包含所有必要信息,减少数据库查询
标准化 行业标准,各种语言都有成熟库

⚠️ JWT 的注意事项

安全问题

  1. 不要存储敏感信息(密码等)
  2. 设置合理的过期时间
  3. 使用 HTTPS 防止令牌被截获
  4. 签名密钥要足够复杂

性能考虑

复制代码
// JWT 一旦签发就不可撤销
// 如果需要即时失效,需要额外方案:
// 1. 短过期时间 + 刷新令牌
// 2. 黑名单机制
// 3. 每次验证查库(会失去无状态优势)

🆚 JWT vs Session

对比项 JWT Session
存储位置 客户端 服务器端
跨域支持 需要额外配置
扩展性 好(无状态) 一般(需要共享session)
安全性 依赖签名 依赖session管理
撤销机制 复杂 简单

📊 实际应用场景

Spring Boot 集成示例

复制代码
@Configuration
public class JwtConfig {
    @Bean
    public JwtUtil jwtUtil() {
        return new JwtUtil();
    }
}

@RestController
@RequestMapping("/api/auth")
public class AuthController {
    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody LoginRequest request) {
        // 验证用户
        if (authenticate(request)) {
            String token = jwtUtil.generateToken(request.getUsername());
            return ResponseEntity.ok(new AuthResponse(token));
        }
        return ResponseEntity.status(401).build();
    }
}

拦截器验证

复制代码
@Component
public class JwtInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, 
                           HttpServletResponse response, 
                           Object handler) {
        String token = request.getHeader("Authorization");
        if (token != null && token.startsWith("Bearer ")) {
            token = token.substring(7);
            if (jwtUtil.validateToken(token)) {
                request.setAttribute("username", jwtUtil.getUsernameFromToken(token));
                return true;
            }
        }
        response.setStatus(401);
        return false;
    }
}

📚 最佳实践总结

  1. 使用安全的签名算法(HS256, RS256)
  2. 令牌有效期尽量短(15-30分钟为佳)
  3. 实现刷新令牌机制
  4. 存储在安全的地方(HttpOnly cookies)
  5. 处理令牌泄露(黑名单或短有效期)
  6. 避免在URL中传递(防止日志泄露)
相关推荐
装不满的克莱因瓶15 小时前
链式法则如何传递参数误差 —— 深入理解神经网络中的梯度传播
人工智能·python·深度学习·神经网络·数学·机器学习·ai
Anastasiozzzz15 小时前
从有限状态机到智能体图:传统 FSM 与 Agent Graph的演进
java·人工智能·python·ai
fqbqrr20 小时前
2606C++,C++构的多态
开发语言·c++
biter down21 小时前
从 0 到 1 搭建 Python 接口自动化测试框架(博客系统实战)
开发语言·python
wang090721 小时前
自己动手写一个spring之IOC_2
java·后端·spring
来杯@Java21 小时前
学生选课管理系统(基于springboot+vue前后端分离的项目)计算机毕业设计java
java·spring boot·spring·vue·毕业设计·maven·mybatis
肖永威1 天前
Python多业务并行计算框架插件化演进:从硬编码到动态注册
python·插件化·并行计算·动态注册
yz_aiks1 天前
Linux Jar包配置Systemd自启动实战:从排查到配置全流程
linux·python·jar·自启动·systemd
threelab1 天前
Three.js 物理模拟着色器 | 三维可视化 / AI 提示词
开发语言·前端·javascript·人工智能·3d·着色器