NestJS Passport Local认证请求无响应问题求助
NestJS Passport LocalAuthGuard 请求挂起问题
问题现象
基于NestJS官方文档实现Passport认证系统时,使用LocalAuthGuard处理登录请求时,请求始终处于等待响应状态。调试发现:
LocalAuthGuard.canActivate()中调用super.canActivate(context)返回Promise { <pending> }LocalStrategy的validate方法从未执行
相关代码片段
auth.module.ts
@Module({ controllers: [AuthController], providers: [AuthService, LocalStrategy, JwtStrategy, RefreshJwtStrategy], imports: [ UsersModule, ConfigModule, PassportModule, JwtModule.registerAsync({ inject: [ConfigService], imports: [ConfigModule], useFactory: (configService: ConfigService) => ({ secret: configService.get<string>('JWT_SECRET_KEY'), signOptions: { expiresIn: configService.get<string>('JWT_ACCESS_TOKEN_TTL'), }, }), }), ], }) export class AuthModule {}
auth.service.ts
export class AuthService { constructor( private readonly userRepository: UsersRepository, private readonly jwtService: JwtService, private readonly configService: ConfigService, ) {} /** * Return user with given username and matching password. * @param email User's email. * @param password User's password. */ public async validateUser( email: string, password: string, ): Promise<User | null> { const user = await this.userRepository.getUserByEmail(email); if (user && (await compare(password, user.password))) return user; return null; } public async createTokenPair(user: any): Promise<TokenPairEntity> { // 省略实现 } }
users.repository.ts
@Injectable() export class UsersRepository { public constructor( @InjectModel(User.name) private readonly userModel: Model<User>, ) {} public async getUserByEmail(email: string): Promise<User | null> { return this.userModel.findOne({ email }).select(['-__v']).exec(); } // 省略其他方法 }
auth.strategy.ts(错误版本)
@Injectable() export class LocalStrategy extends PassportStrategy(Passport, 'local') { public constructor(private readonly authService: AuthService) { super({ usernameField: 'email', passwordField: 'password' }); } public async validate(email: string, password: string): Promise<User> { const user = await this.authService.validateUser(email, password); if (!user) throw new UnauthorizedException(); return user; } }
auth.guards.ts
export class LocalAuthGuard extends AuthGuard('local') { public canActivate( context: ExecutionContext, ): boolean | Promise<boolean> | Observable<boolean> { const result = super.canActivate(context); console.log(result); return result; } }
auth.controller.ts
@Controller('auth') export class AuthController { public constructor(private readonly authService: AuthService) {} @Post('login') @UseGuards(LocalAuthGuard) public async login(@Request() req: Req): Promise<TokenPairEntity> { return this.authService.createTokenPair(req.user); } }
问题原因及解决方案
1. 核心错误:LocalStrategy继承参数错误
PassportStrategy的第一个参数必须是具体的Passport策略实现(如passport-local的Strategy),而非Passport类本身。错误的参数导致Passport无法初始化认证流程,Promise一直处于pending状态。
修正后的auth.strategy.ts:
import { Injectable, UnauthorizedException } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; import { Strategy } from 'passport-local'; // 导入正确的Strategy import { AuthService } from './auth.service'; @Injectable() export class LocalStrategy extends PassportStrategy(Strategy, 'local') { constructor(private readonly authService: AuthService) { super({ usernameField: 'email', passwordField: 'password' }); } async validate(email: string, password: string): Promise<any> { const user = await this.authService.validateUser(email, password); if (!user) { throw new UnauthorizedException(); } return user; } }
2. 确保请求体解析正常
Local策略需要从请求体中获取email和password,需确保NestJS已启用请求体解析。在main.ts中确认以下代码存在:
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import * as express from 'express'; async function bootstrap() { const app = await NestFactory.create(AppModule); // 启用请求体解析 app.use(express.json()); app.use(express.urlencoded({ extended: true })); await app.listen(3000); } bootstrap();
注:NestJS默认会启用这些解析中间件,但如果有自定义配置可能需要手动添加。
3. 检查依赖完整性
确保已安装所有必需依赖:
npm install passport passport-local @nestjs/passport @nestjs/jwt bcrypt
内容的提问来源于stack exchange,提问作者Togrul
相关产品推荐
相关产品推荐

