NestJS中argon2验证JWT刷新令牌始终返回true的异常问题
NestJS + Argon2 Refresh Token 验证异常:旧Token始终通过校验
核心问题
调用refreshTokens接口刷新令牌后,使用第一次的旧refresh token再次调用接口,本应返回ForbiddenException,但argon2.verify()始终返回true,导致旧Token可无限次刷新。
可能原因与解决方案
1. 数据库实体缓存未刷新
这是最常见的原因:findAdminById返回的是缓存的旧管理员实体,其refreshToken字段仍是刷新前的旧哈希值,导致旧Token验证时匹配成功。
解决:
如果使用TypeORM,在查询时强制从数据库重新加载实体,跳过缓存:
// admin.service.ts 中的 findAdminById 方法 async findAdminById(userId: number) { return this.adminRepository.findOne({ where: { id: userId }, reload: true // 关键:强制刷新,获取最新数据 }); }
如果有自定义缓存(如Redis),确保查询管理员信息时禁用缓存,直接读取数据库。
2. 数据库更新操作未生效
检查adminService.updateRefreshToken是否正确将新哈希写入数据库:
正确实现示例:
// admin.service.ts 中的 updateRefreshToken 方法 async updateRefreshToken(userId: number, hash: string) { const updateResult = await this.adminRepository.update( { id: userId }, { refreshToken: hash } ); // 验证更新是否成功,避免静默失败 if (updateResult.affected === 0) { throw new Error('Failed to update refresh token for admin'); } }
手动查看数据库,确认第一次刷新后refreshToken字段确实被替换为新哈希值。
3. Argon2 哈希参数不一致
确保哈希和验证时的Argon2参数完全统一,避免因参数差异导致验证逻辑异常:
统一哈希参数:
// 在 hashData 方法中显式指定参数 async hashData(data: string) { return argon2.hash(data, { type: argon2.argon2id, // 推荐使用安全的 argon2id 类型 memoryCost: 65536, // 64MB 内存开销 timeCost: 3, // 迭代次数 parallelism: 2 // 并行度 }); }
Argon2验证时会从哈希值中解析参数,只要哈希时参数固定,验证就会自动匹配。
4. 调试确认Token与哈希匹配关系
在refreshTokens方法中添加日志,确认存储的哈希与传入的旧Token是否真的匹配:
async refreshTokens(userId: number, rt: string, res: Response): Promise<AccessToken> { const admin = await this.adminService.findAdminById(userId) if (!admin || !admin.refreshToken) throw new ForbiddenException('Access denied') // 添加调试日志 console.log('Stored refresh token hash:', admin.refreshToken); console.log('Received refresh token:', rt); // 手动生成旧Token的哈希,对比存储值 const oldRtHash = await this.hashData('这里替换成第一次的旧Token字符串'); console.log('Old token generated hash:', oldRtHash); const rtMatches = await argon2.verify(admin.refreshToken, rt) if (!rtMatches) throw new ForbiddenException('Access denied') // ... 剩余逻辑 }
如果存储的哈希和旧Token生成的哈希完全一致,说明数据库更新未生效;如果不一致但验证仍返回true,需检查Argon2的依赖版本是否存在bug。
内容的提问来源于stack exchange,提问作者Dmytro
相关产品推荐
相关产品推荐

