当前位置: 首页 > news >正文

JWT令牌机制完全指南

JWT令牌机制完全指南

前言

JWT(JSON Web Token)是现代应用中最常用的令牌格式,具有无状态、可验证的特点。本文将详细介绍JWT的实现和使用。

一、JWT结构

1.1 JWT组成

┌─────────────────────────────────────────────────────┐ │ JWT Structure │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ Header │ │ Payload │ │ Signature │ │ │ │ eyJhbGci...│ │ eyJzdWIiL...│ │ QjJhNmRp... │ │ │ └──────────────┘ └──────────────┘ └──────────────┘ │ │ Base64 Base64 Base64 │ └─────────────────────────────────────────────────────┘

二、JWT实现

2.1 JWT工具类

@Service @RequiredArgsConstructor public class JwtTokenProvider { private final AppProperties appProperties; public String generateToken(Authentication authentication) { UserPrincipal userPrincipal = (UserPrincipal) authentication.getPrincipal(); Date now = new Date(); Date expiryDate = new Date(now.getTime() + appProperties.getJwt().getExpirationMs()); return Jwts.builder() .setSubject(userPrincipal.getId().toString()) .claim("username", userPrincipal.getUsername()) .claim("email", userPrincipal.getEmail()) .claim("roles", userPrincipal.getAuthorities().stream() .map(GrantedAuthority::getAuthority) .collect(Collectors.toList())) .setIssuedAt(now) .setExpiration(expiryDate) .signWith(SignatureAlgorithm.HS512, appProperties.getJwt().getSecret()) .compact(); } public String generateTokenFromUserId(Long userId, String username) { Date now = new Date(); Date expiryDate = new Date(now.getTime() + appProperties.getJwt().getExpirationMs()); return Jwts.builder() .setSubject(userId.toString()) .claim("username", username) .setIssuedAt(now) .setExpiration(expiryDate) .signWith(SignatureAlgorithm.HS512, appProperties.getJwt().getSecret()) .compact(); } public Long getUserIdFromToken(String token) { Claims claims = Jwts.parser() .setSigningKey(appProperties.getJwt().getSecret()) .parseClaimsJws(token) .getBody(); return Long.parseLong(claims.getSubject()); } public String getUsernameFromToken(String token) { Claims claims = Jwts.parser() .setSigningKey(appProperties.getJwt().getSecret()) .parseClaimsJws(token) .getBody(); return claims.get("username", String.class); } public List<String> getRolesFromToken(String token) { Claims claims = Jwts.parser() .setSigningKey(appProperties.getJwt().getSecret()) .parseClaimsJws(token) .getBody(); return claims.get("roles", List.class); } public boolean validateToken(String authToken) { try { Jwts.parser() .setSigningKey(appProperties.getJwt().getSecret()) .parseClaimsJws(authToken); return true; } catch (SecurityException ex) { logger.error("Invalid JWT signature"); } catch (MalformedJwtException ex) { logger.error("Invalid JWT token"); } catch (ExpiredJwtException ex) { logger.error("Expired JWT token"); } catch (UnsupportedJwtException ex) { logger.error("Unsupported JWT token"); } catch (IllegalArgumentException ex) { logger.error("JWT claims string is empty"); } return false; } }

2.2 Token刷新

@Service @RequiredArgsConstructor public class TokenRefreshService { private final JwtTokenProvider tokenProvider; private final RedisTemplate<String, String> redisTemplate; public String refreshToken(String refreshToken) { if (!tokenProvider.validateToken(refreshToken)) { throw new TokenException("Invalid refresh token"); } // 检查refresh token是否在黑名单 if (isTokenBlacklisted(refreshToken)) { throw new TokenException("Refresh token has been revoked"); } Long userId = tokenProvider.getUserIdFromToken(refreshToken); String username = tokenProvider.getUsernameFromToken(refreshToken); // 生成新的access token return tokenProvider.generateTokenFromUserId(userId, username); } public void revokeRefreshToken(String refreshToken) { // 将refresh token加入黑名单 String key = "refresh_token:blacklist:" + refreshToken; long expiration = tokenProvider.getExpiration(refreshToken); redisTemplate.opsForValue().set(key, "revoked", Duration.ofMillis(expiration)); } private boolean isTokenBlacklisted(String token) { String key = "refresh_token:blacklist:" + token; return Boolean.TRUE.equals(redisTemplate.hasKey(key)); } }

三、总结

JWT是实现无状态认证的核心技术,通过合理的生成、验证和刷新机制,可以构建安全可靠的身份认证系统。

http://www.cnnetsun.cn/news/2549683.html

相关文章:

  • Keil MDK优化级别设置与嵌入式开发性能调优
  • ViVeTool-GUI专业指南:解锁Windows隐藏功能的智能方案
  • 别再踩坑了!Ubuntu 22.04 上编译 Mbedtls 3.6 的完整避坑指南(附 Python 依赖解决)
  • 告别虚拟机!保姆级教程:在Win11上用WSL2+Ubuntu 22.04跑起你的第一个Linux桌面
  • 《Java 100 天进阶之路》第12篇:Java对象、类、抽象类、构造方法
  • 机器学习数据集详解,公开免费数据集获取渠道汇总
  • 从零构建通用关系数据库系统:总体设计方案
  • 2026电工杯数学建模竞赛A题论文、代码、数据(改进)
  • 2026保姆级免费去图片水印教程,这4款微信小程序一键搞定
  • VMware虚拟机里装FydeOS,给旧电脑或MacBook找个轻量‘副系统’
  • Unity新手村:用Terrain工具5分钟搭出你的第一个3D场景(含环境包导入)
  • 从HaGRID到自定义:手部关键点数据集标注、转换与可视化实战(Python代码)
  • 别再乱改lightdm.conf了!深入理解LightDM钩子脚本,精准控制Arctica-greeter显示缩放
  • Unity UI Toolkit避坑指南:3D世界UI、动画与Shader,这些事它真做不了
  • 告别虚拟机!手把手教你用U盘给新电脑装Win11+统信UOS双系统(保姆级分区教程)
  • GCN vs MLP:在Cora数据集上,图神经网络到底强在哪?(附可视化对比)
  • 极验4滑块验证码纯算实现:WASM逆向与AES-HMAC算法复现
  • Prompt设计黄金公式首次公开,从“为什么鸡过马路”到“量子态薛定谔猫谜题”,10分钟定制专属脑力挑战库,限前500名领取模板包
  • 电脑关机关不掉?可能是‘快速启动’在捣鬼!保姆级禁用教程与原理浅析
  • K6云原生性能测试:JavaScript脚本+Go运行时的现代压测实践
  • ChatGPT企业版与Microsoft 365 Copilot、Gemini for Workspace横向测评(2024Q2真实POC数据)
  • pion/webrtc v4.2.13:SCTP统计信息曝光、DataChannel并发与关闭竞态修复、测试稳定性提升、依赖升级一次看懂
  • 从GEO数据到小鼠模型:手把手复现一篇7分+动脉粥样硬化多组学文章的分析流程
  • AI Agent的场景选择框架:从高价值到高可行性的评估矩阵
  • 无头服务器玩转CARLA仿真:Ubuntu 20.04离线/无显示器模式下的服务端部署与客户端连接实战
  • QM/MM与ML/MM模拟对比:从呋喃光化学弛豫看机器学习力场结构保真度
  • 工业级大模型学习之路024:LangChain零基础入门教程(第七篇):RAG 系统评估、全链路调优
  • Sysinternals Autoruns深度指南:不止于查毒,更是Windows系统管理的瑞士军刀
  • 17.通杀安卓 /iOS 全机型!Linux 原生刷机方案,EDL 底层救砖 + 自动化源码开源
  • 【万字文档+源码】基于SpringBoot+Vue高校实验室预约系统-计算机专业项目设计分享