您的当前位置:首页 >焦点 >JWT与Token+Redis,哪种方案更好用? 正文
时间:2025-11-05 07:09:17 来源:网络整理编辑:焦点
前言今天我们来聊聊一个非常经典的话题:JWT和Token+Redis两种认证方案,到底哪种更好用?有些小伙伴在工作中可能会纠结于选择哪种方案,今天我就从底层原理到实际应用,给大家做一个全面的剖析。希望
今天我们来聊聊一个非常经典的更好话题:JWT和Token+Redis两种认证方案,到底哪种更好用?更好
有些小伙伴在工作中可能会纠结于选择哪种方案,今天我就从底层原理到实际应用,更好给大家做一个全面的更好剖析。
希望对你会有所帮助。更好
在深入讨论之前,更好我们先明确两个基本概念:
认证(Authentication):你是更好谁?验证用户身份的过程授权(Authorization):你能做什么?验证用户权限的过程无论是JWT还是Token+Redis,都是更好用来解决这两个问题的技术方案。
图片
JWT(JSON Web Token)是一种开放标准(RFC 7519),用于在各方之间安全地传输信息作为JSON对象。更好JWT由三部分组成:
复制header.payload.signature1. Header:包含令牌类型和签名算法Payload:包含声明(用户信息、更好过期时间等)Signature:用于验证消息在传输过程中没有被篡改让我们通过一个完整的登录流程来理解JWT的工作原理:
图片
下面是一个简单的JWT工具类实现:
复制import io.jsonwebtoken.*; import io.jsonwebtoken.security.Keys; import java.security.Key; import java.util.Date; public class JwtUtil { // 密钥,实际项目中应从配置中读取 private static final Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256); // 过期时间:2小时 private static final long EXPIRATION_TIME = 2 * 60 * 60 * 1000; /** * 生成JWT */ public static String generateToken(String userId,更好 String username, List<String> roles) { return Jwts.builder() .setSubject(userId) .claim("username", username) .claim("roles", roles) .setIssuedAt(new Date()) .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) .signWith(key) .compact(); } /** * 验证并解析JWT */ public static Claims parseToken(String token) { try { return Jwts.parserBuilder() .setSigningKey(key) .build() .parseClaimsJws(token) .getBody(); } catch (ExpiredJwtException e) { thrownew RuntimeException("Token已过期", e); } catch (JwtException e) { thrownew RuntimeException("Token无效", e); } } /** * 刷新Token */ public static String refreshToken(String token) { Claims claims = parseToken(token); return generateToken(claims.getSubject(), claims.get("username", String.class), claims.get("roles", List.class)); } }1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.47.48.49.50.51.52.53.优点:
无状态:服务端不需要存储会话信息跨域友好:适合分布式系统和微服务架构自包含:令牌中包含所有必要信息扩展性好:可以轻松添加自定义声明缺点:
无法主动失效:一旦签发,在到期前一直有效令牌大小:包含的企商汇信息越多,令牌越大安全性依赖:完全依赖签名,密钥泄露后果严重Token+Redis方案使用随机生成的令牌作为用户会话的标识,将会话数据存储在Redis中。
这种方案本质上是有状态的,服务端需要维护会话状态。
图片
优点:
主动控制:可以随时使特定令牌失效信息量小:令牌只是一个标识符,不会太大灵活性高:可以存储复杂的会话状态安全性好:令牌泄露可以立即撤销缺点:
有状态:服务端需要存储会话信息Redis依赖:Redis成为单点故障源网络开销:每次请求都需要查询Redis扩展性挑战:需要处理Redis集群和数据同步从性能角度,两种方案有显著差异:
方面
JWT
Token+Redis
认证速度
快(本地验证)
慢(需要Redis查询)
网络开销
小
大(每次请求都需要访问Redis)
服务端压力
小
大(Redis需要处理大量查询)
扩展成本
低
高(需要维护Redis集群)
安全性是认证方案的核心考量因素:
JWT安全性考虑:
密钥管理:签名密钥需要严格保护,定期轮换令牌泄露:无法主动失效,只能等待自动过期算法选择:需要选择安全的签名算法(如HS256、RS256)Token+Redis安全性考虑:
Redis安全:需要保证Redis实例的安全性令牌随机性:令牌必须足够随机,防止猜测传输安全:需要HTTPS防止令牌被窃听不同的业务场景适合不同的方案:
适合JWT的场景:
分布式系统和微服务架构需要跨域认证的单页应用(SPA)无状态API服务移动应用后端适合Token+Redis的云服务器提供商场景:
需要精细控制会话的企业应用需要实时吊销权限的系统会话信息复杂的传统Web应用对安全性要求极高的金融系统有些小伙伴在工作中可能会想:能不能结合两种方案的优点?
答案是肯定的!
下面介绍一种混合方案:
这种方案使用短期有效的JWT,配合Redis黑名单实现主动注销:
复制public class HybridAuthManager { private final JwtUtil jwtUtil; private final RedisTemplate<String, Object> redisTemplate; // JWT短期有效期:15分钟 private static final long SHORT_EXPIRATION = 15 * 60 * 1000; // 刷新令牌有效期:7天 private static final long REFRESH_EXPIRATION = 7 * 24 * 60 * 60 * 1000; /** * 生成访问令牌和刷新令牌 */ public AuthResponse generateTokenPair(User user) { // 生成短期访问令牌 String accessToken = jwtUtil.generateToken( user.getId(), user.getUsername(), user.getRoles(), SHORT_EXPIRATION); // 生成长期刷新令牌 String refreshToken = UUID.randomUUID().toString(); // 存储刷新令牌到Redis storeRefreshToken(refreshToken, user.getId()); returnnew AuthResponse(accessToken, refreshToken); } /** * 刷新访问令牌 */ public String refreshAccessToken(String refreshToken) { // 验证刷新令牌有效性 String userId = validateRefreshToken(refreshToken); if (userId == null) { thrownew RuntimeException("刷新令牌无效"); } // 获取用户信息 User user = userService.getUserById(userId); // 生成新的访问令牌 return jwtUtil.generateToken( user.getId(), user.getUsername(), user.getRoles(), SHORT_EXPIRATION); } /** * 注销令牌 */ public void logout(String accessToken, String refreshToken) { // 将访问令牌加入黑名单(剩余有效期内) Claims claims = jwtUtil.parseToken(accessToken); long expiration = claims.getExpiration().getTime() - System.currentTimeMillis(); if (expiration > 0) { redisTemplate.opsForValue().set( "blacklist:" + accessToken, "logout", expiration, TimeUnit.MILLISECONDS ); } // 删除刷新令牌 if (refreshToken != null) { redisTemplate.delete("refresh_token:" + refreshToken); } } /** * 验证令牌是否在黑名单中 */ public boolean isTokenBlacklisted(String token) { return redisTemplate.hasKey("blacklist:" + token); } }1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.23.24.25.26.27.28.29.30.31.32.33.34.35.36.37.38.39.40.41.42.43.44.45.46.47.48.49.50.51.52.53.54.55.56.57.58.59.60.61.62.63.64.65.66.67.68.69.70.71.72.73.74.
图片
根据我多年的工作经验,给大家一些实用的选型建议:
通过上面的详细分析,JWT和token+redis这两种方案,各有优缺点和适用场景。
我们可以得出以下结论:
没有绝对的最好方案:只有最适合具体业务场景的方案。JWT优势在无状态和扩展性:适合分布式系统和API优先的架构。Token+Redis优势在控制和灵活性:适合需要精细会话管理的企业应用。混合方案取长补短:适合大多数现代Web应用。有些小伙伴在工作中可能会盲目追求技术的新颖性,或者过度设计认证方案。
我的建议是:从实际业务需求出发,选择最简单可靠的方案。
对于大多数应用来说,我推荐采用混合方案:
使用短期JWT保证API的无状态特性。使用刷新令牌机制优化用户体验。使用Redis黑名单提供主动注销能力。使用HTTPS和严格的密钥管理保证安全性。无论选择哪种方案,都要记住:安全不是一个功能,而是一个过程。
希望这篇文章能帮助大家在技术选型时做出更明智的决策。
优化工作效率,轻松锁定MacBook(通过设置快捷键,实现一键锁屏,提升工作效率)2025-11-05 06:58
酷乐视Q7投影仪的性特点(探索Q7的智能功能与高品质投影体验)2025-11-05 06:17
ZMI随身WiFi如何满足你的上网需求?(便携、稳定、高速,体验全新的无线上网方式)2025-11-05 05:39
探索MDR100AAP耳机的音质与舒适度(为你带来纯净的音乐享受和极致的佩戴体验)2025-11-05 05:36
如何更换SSD硬盘(教你一步步更换电脑的SSD硬盘,提升系统速度和性能)2025-11-05 05:36
异种态(解锁最强蜗牛异种态的关键与方法)2025-11-05 04:50
使用U盘做系统教程(一步一步教你如何使用U盘安装和运行自己喜欢的操作系统)2025-11-05 04:50
艾利和H120光纤(性能稳定可靠的光纤产品,艾利和H120光纤的优势分析)2025-11-05 04:49
vivo手机4寸屏手机的特点与优势(小巧便携,功能强大,实用性超越预期)2025-11-05 04:28
三星14纳米技术的革新之路(揭秘三星14纳米工艺的突破和应用前景)2025-11-05 04:27
网络设置中缺少WLAN选项的解决方法(如何解决设备中找不到WLAN选项的问题)2025-11-05 07:06
使用WDR5600刷OpenWrt的完整教程2025-11-05 07:05
AMDR9380显卡(解析AMDR9380显卡的优势及应用范围)2025-11-05 06:16
联想G50-75m笔记本电脑性能如何?(一探联想G50-75m笔记本电脑的配置和使用体验)2025-11-05 06:11
如何将手机中的大视频传输到电脑2025-11-05 06:01
探索以玩家国度的魅力(一窥游戏世界的独特精髓)2025-11-05 05:06
电脑连接耳机指南(轻松享受高品质音乐的简便方法)2025-11-05 05:06
使用Ghost镜像快速安装操作系统(简化步骤,轻松完成安装)2025-11-05 04:49
使用U盘进行Win10重装的教程(简单易行的步骤,让你轻松重装系统)2025-11-05 04:40
三洋PLC-XU50的特点与性能分析(探究三洋PLC-XU50的可靠性与高效性能)2025-11-05 04:38