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中传递(防止日志泄露)
相关推荐
爬山算法几秒前
Hibernate(88)如何在负载测试中使用Hibernate?
java·后端·hibernate
摘星编程几秒前
解析CANN ops-nn中的Transpose算子:张量维度变换的高效实现
python
自不量力的A同学4 分钟前
Solon AI v3.9 正式发布:全能 Skill 爆发
java·网络·人工智能
Liekkas Kono8 分钟前
RapidOCR Python 贡献指南
开发语言·python·rapidocr
张张努力变强15 分钟前
C++ STL string 类:常用接口 + auto + 范围 for全攻略,字符串操作效率拉满
开发语言·数据结构·c++·算法·stl
万岳科技系统开发16 分钟前
食堂采购系统源码库存扣减算法与并发控制实现详解
java·前端·数据库·算法
xyq202417 分钟前
Matplotlib 绘图线
开发语言
独断万古他化19 分钟前
【Spring 原理】Bean 的作用域与生命周期
java·后端·spring
玄同76520 分钟前
Python 后端三剑客:FastAPI/Flask/Django 对比与 LLM 开发选型指南
人工智能·python·机器学习·自然语言处理·django·flask·fastapi
m0_6948455721 分钟前
tinylisp 是什么?超轻量 Lisp 解释器编译与运行教程
服务器·开发语言·云计算·github·lisp