NestJS Passport AuthGuard无法验证有效Token,返回401或无效签名
问题:JWT手动验证正常但AuthGuard('jwt')返回401/无效签名
本地策略生成的Token,通过JwtService.verify(token)可正常验证并返回Payload,但使用@UseGuards(AuthGuard('jwt'))装饰器时,接口返回401 Unauthorized或Invalid signature,且无法获取req.user。
1. 手动验证代码(可正常返回Payload)
// auth.controller.ts // ... @Post(`/verify`) async verify(@Request() req, @Headers() headers) { const authHeader = headers['authorization'] // 手动获取Authorization头值 const token = authHeader.substring('Bearer '.length) // 移除Bearer前缀 return this.jwtService.verify(token) }
2. 使用AuthGuard的代码(无法获取req.user)
// auth.controller.ts // ... @UseGuards(AuthGuard('jwt')) @Post(`/verify`) async verify(@Request() req, @Headers() headers) { return(req.user) }
3. JWT策略配置
import { Injectable } from '@nestjs/common' import { PassportStrategy } from '@nestjs/passport' import { ExtractJwt, Strategy } from 'passport-jwt' @Injectable() export class JwtStrategy extends PassportStrategy(Strategy) { constructor() { super({ jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), ignoreExpiration: false, secretOrKey: `${process.env.JWT_SECRET}`, }) } async validate(username: string, password: string) { return { username, password } } }
4. AuthModule配置
// auth.module.ts // ... @Module({ imports: [ PassportModule.register({ defaultStrategy: 'jwt' }), MongooseModule.forFeature([ { name: User.name, schema: UserSchema, }, ]), JwtModule.register({ secret: `${process.env.JWT_SECRET}`, signOptions: { expiresIn: '60d', }, }), ], controllers: [AuthController], providers: [ AuthService, UserService, HashService, LocalStrategy, JwtStrategy, ], }) export class AuthModule {}
5. 自定义JwtAuthGuard尝试结果
自定义Guard的canActivate方法能正确读取并验证Token(可正常打印Payload),但handleRequest仍返回未授权,日志显示Jsonwebtokenerror: Invalid Signature:
// jwt-gaurd.ts import { ExecutionContext, Injectable } from '@nestjs/common' import { AuthGuard } from '@nestjs/passport' import { JwtService } from '@nestjs/jwt' @Injectable() export class JwtAuthGuard extends AuthGuard('jwt') { constructor(private jwtService: JwtService) { super({ secret: `${process.env.JWT_SECRET}`, signOptions: { expiresIn: '60d', }, }) } async canActivate(context: ExecutionContext) { const request = context.switchToHttp().getRequest() const token = request.headers.authorization.split(' ')[1] try { const payload = await this.jwtService.verify(token) console.log(payload) // 可正常打印Payload super.canActivate(context) return true } catch (error) { return false } } async validate(payload: any) { return payload } handleRequest(err, user, info) { console.log(err, user, info) if (err || !user) { return err } return user } }
已排查项
- 多处提取的Token均能正常验证并获取Payload
- 所有配置中的
secret已核对一致 - 依赖导入无问题
寻求解决该问题的可行方案。
内容的提问来源于stack exchange,提问作者another dolphin
相关产品推荐
相关产品推荐

