NestJS 未知身份验证策略“本地”

问题描述 投票:0回答:2

我在 NestJs 中有这段代码,其中包含以下文件,但现在它显示“未知的身份验证策略“本地””, 我已经寻找解决方案,它们都指向导入错误,但我已将 localstrategy 导入到 auth.module 和 app.module 中(我已经测试过将其从 app.module 中取出,但它不会改变任何内容.)

app.module.ts

    import { Module } from '@nestjs/common';
    import { AppController } from './app.controller';
    import { AppService } from './app.service';
    import { ThrottlerModule } from '@nestjs/throttler';
    import { MongooseModule } from '@nestjs/mongoose';
    import { AuthModule } from './auth/auth.module';
    import { UsersModule } from './users/users.module';
    import { LocalStrategy } from './auth/local.strategy';

    @Module({
      imports: [
        MongooseModule.forRoot(
          'mongodb+srv://user:[email protected]/db?retryWrites=true&w=majority',
        ),
        ThrottlerModule.forRoot({
          ttl: 60,
          limit: 10,
        }),
        AuthModule,
        UsersModule,
      ],
      controllers: [AppController],
      providers: [AppService, LocalStrategy],
    })
    export class AppModule {}

auth.module.ts

      import { Module } from '@nestjs/common';
  import { AuthService } from './auth.service';
  import { UsersModule } from '../users/users.module';
  import { PassportModule } from '@nestjs/passport';
  import { LocalStrategy } from './local.strategy';
  import { JwtModule } from '@nestjs/jwt';
  import { JwtStrategy } from './jwt.strategy';
  import 'dotenv/config';

  @Module({
    imports: [
      UsersModule,
      PassportModule,
      JwtModule.register({
        secret: process.env.JWTSECRET,
        signOptions: { expiresIn: '60s' },
      }),
    ],
    providers: [AuthService, LocalStrategy, JwtStrategy],
    exports: [AuthService],
  })
  export class AuthModule {}

本地.strategy.ts

      import { Strategy } from 'passport-local';
  import { PassportStrategy } from '@nestjs/passport';
  import { Injectable, UnauthorizedException } from '@nestjs/common';
  import { AuthService } from './auth.service';

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

    async validate(email: string, password: string): Promise<any> {
      const user = await this.authService.validateUser(email, password);
      if (!user) {
        throw new UnauthorizedException();
      }
      return user;
    }
  }

app.controller.ts

    import {
  Controller,
  Request,
  Post,
  UseGuards,
  Res,
  Get,
  Body,
} from '@nestjs/common';
import { AuthService } from './auth/auth.service';
import { MakeAuthDto } from './auth/dto/make-auth.dto';
import { JwtAuthGuard } from './auth/jwt-auth.guard';
import { LocalAuthGuard } from './auth/local-auth.guard';
import { Roles } from './utils/decorators/roles.decorator';
import { Role } from './utils/enums/role.enum';
import { RolesGuard } from './utils/guards/roles.guard';

@Controller()
export class AppController {
  constructor(private authService: AuthService) {}

  @UseGuards(LocalAuthGuard)
  @Post('auth/login')
  async login(
    @Body() _: MakeAuthDto,
    @Request() req,
    @Res({ passthrough: true }) res,
  ) {
    console.log(req.user);
    const access_token = await this.authService.login(req.user);
    res.cookie('jwt', access_token);
    return req.user;
  }

  @UseGuards(JwtAuthGuard, RolesGuard)
  @Roles(Role.Admin)
  @Get('tests')
  getProfile(@Request() req) {
    return req.user;
  }
}

本地auth.guard.ts

        import { Injectable } from '@nestjs/common';
    import { AuthGuard } from '@nestjs/passport';

    @Injectable()
    export class LocalAuthGuard extends AuthGuard('local') {}

auth.service.ts

    import { Injectable } from '@nestjs/common';
import { UsersService } from 'src/users/users.service';
import { JwtService } from '@nestjs/jwt';
import { UserDocument } from 'src/users/entities/user.entity';

@Injectable()
export class AuthService {
  constructor(
    private usersService: UsersService,
    private jwtService: JwtService,
  ) {}

  async validateUser(email: string, pass: string): Promise<UserDocument | any> {
    const user = await this.usersService.findOne(email);
    if (user && (await user.compareHash(pass))) {
      const { password, ...result } = user.toObject();
      await this.usersService.updateLastLogin(user._id);
      return result;
    }
    return null;
  }

  async login(user: UserDocument): Promise<string> {
    const payload = { email: user.email, sub: user._id, roles: user.roles };
    return this.jwtService.sign(payload);
  }
}

jwt-auth.guard.ts

        import { Injectable } from '@nestjs/common';
    import { AuthGuard } from '@nestjs/passport';

    @Injectable()
    export class JwtAuthGuard extends AuthGuard('jwt') {}

jwt.strategy.ts

    import { ExtractJwt, Strategy } from 'passport-jwt';
import { PassportStrategy } from '@nestjs/passport';
import { Injectable } from '@nestjs/common';
import 'dotenv/config';

const cookieExtractor = function (req) {
  let token = null;
  if (req && req.cookies) {
    token = req.cookies['jwt'];
  }
  return token;
};

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super({
      jwtFromRequest: ExtractJwt.fromExtractors([cookieExtractor]),
      ignoreExpiration: false,
      secretOrKey: process.env.JWTSECRET,
    });
  }

  async validate(payload: any) {
    return { userId: payload.sub, email: payload.email, roles: payload.roles };
  }
}

stackoverflow 上没有类似的问题解决了我的问题,有人知道它是什么吗?

node.js typescript passport.js nestjs passport-local
2个回答
2
投票

最近我最终遇到了这个错误,因为我对文件夹的组织似乎找不到文件

local.strategy
jwt.strategy
,在每个Guard中我必须添加一个导入策略的构造函数。

目前你的代码是这样的:

import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class LocalAuthGuard extends AuthGuard('local') {}

通过添加如下结构来更改文件:

import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

import { LocalStrategy } from './local.strategy';

@Injectable()
export class LocalAuthGuard extends AuthGuard('local') {
  constructor(private readonly localStrategy: LocalStrategy) {
    super();
  }
}

如果这不起作用,则此错误的真正原因与作用域请求注入有关,显然中间件必须忽略

LocalAuthGuard
中间件的执行。例如:一个多租户连接,如果你从请求中获取数据库的名称,最终可能会忽略 LocalAuthGuard 的执行,因为在文件
local.strategy.ts
中你正在使用构造函数
private authService: AuthService
并且如果它真的是进行多租户连接检查如何将存储库注入名为
UsersService
的文件中。

希望这可以帮助任何遇到此错误的人。


0
投票

谢谢内森·奥利维拉。

你又救了我一天。我想知道为什么我的 LocalAuthGuard 不起作用。在我像你一样修改我的代码后,它修复了它。

我仍在阅读您的评论,以了解问题的真正原因。

事实上,我正在尝试构建一个多租户应用程序,其中我使用 PrismaService 的 Request Scope 进行数据库连接。

@Injectable({scope:Scope.REQUEST}) 导出类 PrismaService 实现 OnModuleInit、OnModuleDestroy {

谢谢。

© www.soinside.com 2019 - 2024. All rights reserved.