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中传递(防止日志泄露)
相关推荐
2501_944424124 小时前
Flutter for OpenHarmony游戏集合App实战之消消乐下落填充
android·开发语言·flutter·游戏·harmonyos
min1811234564 小时前
软件升级全流程步骤详解
android·java·服务器
黎雁·泠崖4 小时前
Java字符串系列总结篇|核心知识点速记手册
java·开发语言
biyezuopinvip4 小时前
基于Spring Boot的社区互助平台设计与实现(毕业论文)
java·spring boot·vue·毕业设计·论文·毕业论文·社区互助平台设计与实现
Agilex松灵机器人4 小时前
持续更新|从零到玩转Moveit机械臂控制(一)
人工智能·python·机器人·学习方法
喵手5 小时前
《Python爬虫工程化实战》专栏导读|从“脚本能跑”到“系统能交付”:零基础也能做出可部署的 Python 爬虫!
爬虫·python·网络爬虫·爬虫实战·python爬虫·python爬虫工程化·爬虫实战教学
JNU freshman5 小时前
从 Ceph 16(Pacific)到 Ceph 18(Reef):cephadm 的伸缩性演进与 cephadm agent 到底“成熟”了吗?
java·大数据·ceph
彩妙不是菜喵5 小时前
STL精讲:string类
开发语言·c++