如何在NestJS Passport-JWT中区分请求拒绝的不同原因?
区分NestJS Passport-JWT认证失败原因的解决方案
核心思路是通过自定义JWT Auth Guard,捕获Passport-JWT抛出的不同类型错误,返回对应明确的错误信息给客户端。
1. 自定义JWT Auth Guard
创建继承自AuthGuard('jwt')的自定义Guard,重写handleRequest方法来识别不同的认证失败场景:
import { Injectable, UnauthorizedException } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; import { TokenExpiredError, JsonWebTokenError } from 'jsonwebtoken'; @Injectable() export class JwtAuthGuard extends AuthGuard('jwt') { handleRequest(err: any, user: any, info: any) { // 令牌过期场景 if (info instanceof TokenExpiredError) { throw new UnauthorizedException('令牌已过期'); } // 令牌无效场景(如签名错误、格式非法) if (info instanceof JsonWebTokenError) { throw new UnauthorizedException('令牌无效'); } // 未提供令牌场景 if (info?.message === 'No auth token') { throw new UnauthorizedException('未提供访问令牌'); } // 其他未覆盖的认证失败场景 if (err || !user) { throw err || new UnauthorizedException('认证失败'); } return user; } }
2. 替换默认Guard使用自定义实现
在需要认证的路由或控制器上,用自定义的JwtAuthGuard替代默认的AuthGuard('jwt'):
import { Controller, Get, UseGuards } from '@nestjs/common'; import { JwtAuthGuard } from './jwt-auth.guard'; @Controller('api') export class ProtectedController { @Get('protected') @UseGuards(JwtAuthGuard) getProtectedContent() { return { data: '这是受JWT保护的内容' }; } }
3. 全局使用自定义Guard(可选)
如果希望所有路由默认启用该认证逻辑,可在根模块中配置全局Guard:
import { APP_GUARD } from '@nestjs/core'; import { JwtAuthGuard } from './jwt-auth.guard'; @Module({ providers: [ { provide: APP_GUARD, useClass: JwtAuthGuard, }, ], }) export class AppModule {}
完成以上配置后,客户端会收到明确的错误响应:
- 未提供令牌:
401 {"message": "未提供访问令牌", "statusCode": 401} - 令牌过期:
401 {"message": "令牌已过期", "statusCode": 401} - 令牌无效:
401 {"message": "令牌无效", "statusCode": 401}
内容的提问来源于stack exchange,提问作者Nelson Teixeira
相关产品推荐
相关产品推荐

