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中传递(防止日志泄露)
相关推荐
云烟成雨TD16 小时前
Spring AI Alibaba 1.x 系列【6】ReactAgent 同步执行 & 流式执行
java·人工智能·spring
Csvn16 小时前
🌟 LangChain 30 天保姆级教程 · Day 13|OutputParser 进阶!让 AI 输出自动转为结构化对象,并支持自动重试!
python·langchain
Wenweno0o16 小时前
0基础Go语言Eino框架智能体实战-chatModel
开发语言·后端·golang
于慨16 小时前
Lambda 表达式、方法引用(Method Reference)语法
java·前端·servlet
swg32132116 小时前
Spring Boot 3.X Oauth2 认证服务与资源服务
java·spring boot·后端
gelald16 小时前
SpringBoot - 自动配置原理
java·spring boot·后端
殷紫川16 小时前
深入理解 AQS:从架构到实现,解锁 Java 并发编程的核心密钥
java
一轮弯弯的明月16 小时前
贝尔数求集合划分方案总数
java·笔记·蓝桥杯·学习心得
chenjingming66616 小时前
jmeter线程组设置以及串行和并行设置
java·开发语言·jmeter
殷紫川16 小时前
深入拆解 Java volatile:从内存屏障到无锁编程的实战指南
java