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中传递(防止日志泄露)
相关推荐
小羊没烦恼!2 天前
微服务化的基石——持续集成
java·大数据·word·powerpoint·.net
默_笙2 天前
🍙 给每个请求过安检:FastAPI 是怎么把校验写进类型注解的
python
俊昭喜喜里2 天前
java中的继承和多态的区别
java
小羊没烦恼!2 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
qq_426003962 天前
启动playwright录制codegen生成自动化测试脚本
python·自动化
譕痕2 天前
JSONObject与JSONArray封装数据格式区别
java·json
虎头金猫2 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
胡写代码2 天前
别再前后端各写一套表单校验了
java·后端
小鱼能吃糖2 天前
缺陷修复总览 · mall电商项目:5类缺陷,1个病根,4个业务域
java·电商
长沙三为智能科技2 天前
家政小程序开发从0到上线:五阶段交付流程与验收清单
python