NestJS集成JWT时req.user始终返回同一用户的问题
NestJS JWT切换用户后req.user不变的解决方案
核心排查方向及修复方案
1. 移除JWT策略中的用户缓存逻辑
如果你的JwtStrategy里用了全局变量缓存用户,会导致所有验证请求都返回第一个缓存的用户。
错误示例:
// 全局变量缓存用户,导致用户不更新 let cachedUser: User; @Injectable() export class JwtStrategy extends PassportStrategy(Strategy) { constructor(private readonly usersService: UsersService) { super({ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), secretOrKey: process.env.JWT_SECRET, }); } async validate(payload: any) { if (!cachedUser) { cachedUser = await this.usersService.findOne(payload.sub); } return cachedUser; } }
修复代码:
@Injectable() export class JwtStrategy extends PassportStrategy(Strategy) { constructor(private readonly usersService: UsersService) { super({ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), secretOrKey: process.env.JWT_SECRET, }); } async validate(payload: any) { // 每次验证都重新查询当前用户 const user = await this.usersService.findOne(payload.sub); if (!user) throw new UnauthorizedException(); return user; } }
2. 检查客户端是否更新了JWT令牌
切换用户时,客户端必须替换请求头中的Authorization: Bearer <token>为新用户的令牌。如果客户端没更新,后端会一直解析旧令牌返回旧用户。
后端验证方式:在控制器中临时添加调试代码,确认请求令牌是否正确:
@Get('/profile') @UseGuards(JwtAuthGuard) getProfile(@Req() req) { console.log('当前请求令牌:', req.headers.authorization?.split(' ')[1]); return req.user; }
3. 修正JWT签发时的用户标识
如果签发JWT时硬编码了用户ID,所有令牌解析后都会指向同一个用户。
错误示例:
async login(@Body() loginDto: LoginDto) { const user = await this.usersService.validateUser(loginDto); // 硬编码用户ID,导致所有令牌的sub都是1 const payload = { username: user.username, sub: 1 }; return { access_token: this.jwtService.sign(payload) }; }
修复代码:
async login(@Body() loginDto: LoginDto) { const user = await this.usersService.validateUser(loginDto); // 使用当前用户的真实ID作为唯一标识 const payload = { username: user.username, sub: user.id }; return { access_token: this.jwtService.sign(payload) }; }
4. 排查全局拦截器/守卫的缓存逻辑
检查全局拦截器或守卫是否存在缓存req.user的逻辑(比如用全局变量存储用户数据),确保所有用户信息处理都基于当前请求对象,不共享全局状态。
5. 确认Passport模块配置正确性
确保JwtModule是全局模块或在需要的模块中正确导入,避免多实例导致的上下文冲突:
@Module({ imports: [ JwtModule.register({ secret: process.env.JWT_SECRET, signOptions: { expiresIn: '60s' }, }), ], providers: [JwtStrategy, AuthService], exports: [AuthService, JwtModule], }) export class AuthModule {}
内容的提问来源于stack exchange,提问作者Luciano Pulido
相关产品推荐
相关产品推荐

