0

我已逐步遵循官方 Nest 文档( https://docs.nestjs.com/security/authentication ),但在使用 @AuthGuard('local') 或 @AuthGuard 时无法调用 validate() 方法(LocalAuthGuard) 登录操作。

如果我不使用那个保护装饰器,一切都会按预期工作(但我需要使用它来将我的令牌添加到请求对象中)。

auth.controller.ts

  @UseGuards(AuthGuard('local')) // or AuthGuard(LocalAuthGuard)
  @Post('login')
  async login(
    @Request() req
  ) {
    const { access_token } = await this.authService.login(req.user);
    return access_token;
  }
}

local.strategy.ts

@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy) {
  constructor(private authService: AuthService) {
    super({ usernameField: 'email' });
  }

  async validate(email: string, password: string): Promise<any> { // class is constructed but this method is never called
    const user: UserDto = await this.authService.login({
      email,
      password,
    });
    
    if (!user) {
      throw new UnauthorizedException();
    }
    return user;
  }
}

auth.module.ts

@Module({
  imports: [
    UsersModule,
    PassportModule,
    JwtModule.register({
      secret: "bidon", 
      signOptions: {
        expiresIn: '3600',
      },
    }),
  ],
  providers: [AuthService, LocalStrategy, JwtStrategy],
  exports: [AuthService, PassportModule, JwtModule],
  controllers: [AuthController],
})
export class AuthModule {}

PS:我已经阅读了所有与堆栈溢出相关的帖子(例如:NestJS' Passport Local Strategy "validate" method never called)但他们没有帮助我。

4

1 回答 1

0

我发现如果我们不通过emailor password,而且两者的值都错误,守卫会响应Unauthorized消息。问题是如果未定义,如何确保在运行保护逻辑之前验证必填字段,换句话说,前端不会将其传递给服务器。如果我们添加@Body() data: loginDto控制器方法,它不会验证主体参数。

为了解决它,我在local.guard.ts文件中添加了一些验证代码。这是我的项目中的代码:

import { HttpException, HttpStatus, Injectable, UnauthorizedException } from "@nestjs/common";
import { AuthGuard } from "@nestjs/passport";

@Injectable()
export class LocalAuthGuard extends AuthGuard('local') {
  handleRequest(err, user, info, context, status) {
    const request = context.switchToHttp().getRequest();
    const { mobile, password } = request.body;
    if (err || !user) {
      if (!mobile) {
        throw new HttpException({ message: '手机号不能为空' }, HttpStatus.OK);
      } else if (!password) {
        throw new HttpException({ message: '密码不能为空' }, HttpStatus.OK);
      } else {
        throw err || new UnauthorizedException();
      }
    }
    return user;
  }
}
于 2022-02-09T04:02:20.870 回答