javascript NestJS -错误:未知身份验证策略“local”

mfuanj7w  于 2022-11-20  发布在  Java
关注(0)|答案(7)|浏览(325)

这是我所拥有的NestJS部分代码片段。我正在尝试实现passport本地策略以获取用户名和密码。我得到-错误:使用auth guard时,控制器文件中的身份验证策略“local”未知。
AuthModule.ts

import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import { UserModule } from 'src/user/user.module';
import { JwtAuthController } from './jwt-auth.controller';
import { JwtAuthService } from './jwt-auth.service';
import { JwtStrategy } from './jwt.strategy';
import { LocalStrategy } from './local.strategy';

@Module({
  imports: [
    UserModule,
    PassportModule,
    JwtModule.register({
      secret: process.env.SECRETKEY,
      signOptions: { expiresIn: '3600s' }
    })
  ],
  controllers: [JwtAuthController],
  providers: [JwtAuthService, LocalStrategy, JwtStrategy],
  exports: [JwtAuthService],
})
export class JwtAuthModule {}

local.strategy.ts

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

@Injectable()
export class LocalStrategy extends PassportStrategy(Strategy, 'local') {
  constructor(private authService: JwtAuthService) {
    super();
  }

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

app.controller.ts

import { Body, Controller, Get, Post, Req, UnauthorizedException, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { JwtAuthService } from './jwt-auth/jwt-auth.service';

@Controller()
export class AppController {

  constructor(private readonly authService: JwtAuthService)  {}
  
  @UseGuards(AuthGuard('local'))
  @Post('/auth/login')
  async login(@Req() req) {
    return this.authService.login(req.user)
  }
  
}

调用/auth/login API时出现以下错误

[Nest] 26753  - 10/31/2021, 22:08:18   ERROR [ExceptionsHandler] Unknown authentication strategy "local"
Error: Unknown authentication strategy "local"

我错过什么了吗?提前谢谢。

ercv8c1e

ercv8c1e1#

只需在应用模块中添加PassportModule和LocalStrategy。它将被修复

@Module({
  imports: [PassportModule],
  providers: [AuthService,LocalStrategy],
 })
 export class AppModule {}
yb3bgrhw

yb3bgrhw2#

修复错误https://github.com/nestjs/nest/issues/4646
文件授权

enter code here

import { Module } from '@nestjs/common';
import { JwtModule } from '@nestjs/jwt';
import { PassportModule } from '@nestjs/passport';
import { UserModule } from 'src/user/user.module';
import { JwtAuthController } from './jwt-auth.controller';
import { JwtAuthService } from './jwt-auth.service';
import { JwtStrategy } from './jwt.strategy';
import { LocalStrategy } from './local.strategy';

@Module({
imports: [
UserModule,
PassportModule.register({defaultStrategy:'local'}),
JwtModule.register({
  secret: process.env.SECRETKEY,
  signOptions: { expiresIn: '3600s' }
})
],
controllers: [JwtAuthController],
providers: [JwtAuthService, LocalStrategy, JwtStrategy],
exports: [JwtAuthService],
})
export class JwtAuthModule {}
xghobddn

xghobddn3#

这么老的问题没有答案......
在我的例子中,我遇到了一个循环依赖问题。或者至少它看起来是这样的。循环依赖可以在nest端,甚至可以在node.js require端(在第二种情况下,我们以空导入结束)。
案例一:

@Injectable()
export class MyLocalStrategy extends PassportStrategy(PassportLocalStrategy) {
  hello = 'hello'

  constructor(private authService: AuthService) {
    console.log('load local strategy')
  }
}

@Module({
  imports: [
    CommonModule,
    PassportModule,
    JwtModule.registerAsync({
      async useFactory(config: ConfigService) {
        const jwtSecret = config.get('APP_KEY')
        const expiresIn = config.get('AUTH_TOKEN_EXPIRED')
        return {
          secret: jwtSecret,
          signOptions: {
            expiresIn,
          },
        }
      },
      inject: [ConfigService],
    }),
  ],
  providers: [
    RoleService,
    JwtStrategy,
    JwtService,
    AuthService,
  ],
  controllers: [AuthController],
  exports: [AuthService],
})
export class AuthModule {
  constructor(private moduleRef: ModuleRef) {}

  onModuleInit() {
    const moduleRef = this.moduleRef
    console.log('init auth module')
    const local = moduleRef.get(MyLocalStrategy)
    const auth = moduleRef.get(AuthService)
    console.log('my modules', { local, auth }, local?.hello)
  }
}

在这种情况下,“load local strategy”从未被记录。然而,“my modules”记录了一个空的localStrategy示例,没有我的“hello”属性。奇怪!
我通过将类示例化移到工厂提供者,并通过要求ModuleRef的依赖项来进行修复。

@Module({
  imports: [
    CommonModule,
    PassportModule,
    JwtModule.registerAsync({
      async useFactory(config: ConfigService) {
        const jwtSecret = config.get('APP_KEY')
        const expiresIn = config.get('AUTH_TOKEN_EXPIRED')
        return {
          secret: jwtSecret,
          signOptions: {
            expiresIn,
          },
        }
      },
      inject: [ConfigService],
    }),
  ],
  providers: [
    RoleService,
    JwtStrategy,
    JwtService,
    AuthService,
    {
      provide: MyLocalStrategy,
      useFactory: (moduleRef: ModuleRef) => {
        const auth = moduleRef.get(AuthService)
        console.log('local strat factory', { auth })
        return new MyLocalStrategy(auth)
      },
      inject: [ModuleRef],
    },
  ],
  controllers: [AuthController],
  exports: [AuthService],
})
export class AuthModule {
  constructor(private moduleRef: ModuleRef) {}

  onModuleInit() {
    const moduleRef = this.moduleRef
    console.log('init auth module')
    const local = moduleRef.get(MyLocalStrategy)
    const auth = moduleRef.get(AuthService)
    console.log('local', { local, auth }, local?.hello)
  }
}

我还尝试了factory +直接注入AuthService(通过提供程序数组,而不是使用ModuleRef)。我得到了一个空的AuthService。
可能是node.js模块导入上的一些依赖循环,坚韧无论是eslint还是nest都不会说什么。

gkn4icbw

gkn4icbw4#

检查验证模块是否导入到条目文件. app.module.ts中。
我的身份验证模块.ts

import { Module } from '@nestjs/common';
import { PassportModule } from '@nestjs/passport';
import { UsersModule } from 'src/users/users.module';
import { AuthService } from './auth.service';
import { LocalStrategy } from './local.strategy';

@Module({
 imports:[UsersModule,PassportModule],
 providers: [AuthService,LocalStrategy]
})
export class AuthModule {}

我的应用模块

import { Module } from '@nestjs/common';
import { PassportModule } from '@nestjs/passport';
import { UsersModule } from 'src/users/users.module';
import { AuthService } from './auth.service';
import { LocalStrategy } from './local.strategy';

@Module({
  imports:[UsersModule,PassportModule],
 providers: [AuthService,LocalStrategy]
})
export class AuthModule {}
tez616oj

tez616oj5#

NestJs 鼓励 可 伸缩 性 , 因此 将 代码 组织 在 模块 中 。 不要 在 AppController 中 调用 JwtAuthService 方法 , 而 应 在 JwtAuthController 中 调用 。 代码 应 如下 所 示 :

import { Body, Controller, Get, Post, Req, UnauthorizedException, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { JwtAuthService } from './jwt-auth.service';

@Controller('auth')
export class JwtAuthController {
  constructor(private readonly authService: JwtAuthService)  {}
  
  @Post('/login')
  @UseGuards(AuthGuard('local'))
  async login(@Req() req) {
    return req.user
  }
  
}

中 的 每 一 个
然后 Nest 将 示例 化 JwtAuthModule 中 的 所有 提供 者 , 以便 在 其 控制 器 ( JwtController ) 中 可用 。
您 总是 可以 通过 将 AuthGuard 移动 到 它 自己 的 文件 local.guard.ts 来 优化 您 的 代码 , 从而 使 您 可以 执行 任何 其他 业务 逻辑 。

import { ExecutionContext } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { Request } from 'express';

export class LocalGuard extends AuthGuard('local') {}

格式

zdwk9cvp

zdwk9cvp6#

您需要导入实现身份验证的模块,它可以位于app.module.ts内部,也可以位于与其连接的另一个模块内部

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { AuthModule } from './auth/auth.module';
import { UsersModule } from './users/users.module';

@Module({
    imports: [UsersModule, AuthModule],
    controllers: [AppController],
    providers: [AppService],
})
export class AppModule {}
xkrw2x1b

xkrw2x1b7#

我的解决方案是将LocalStrategy类导入到模块文件中,其中我使用AuthGuard作为API端点。
例如:在文件user.controller.ts中,我在端点/login中具有AuthGuard('local'),方法为POST

//user.controller.ts

@UseGuards(AuthGuard('local'))
@Post('login')
async login (@Request() req: any) {
  return req.user;
}

在我的例子中,我只是在模块文件中添加了LocalStrategy类(我和你一样在local.strategy.ts中也有这个类):

//user.module.ts

@Module({
  imports: [
    ...
    LocalStrategy,
  ],
  controllers: [UserController],
  ...
}

总结,NestJs导入模块比较复杂,别忘了把你想要的导入到其他模块中,祝你好运!

相关问题