NestJS jwt-passport 身份验证

Posted

技术标签:

【中文标题】NestJS jwt-passport 身份验证【英文标题】:NestJS jwt-passport Authentication 【发布时间】:2019-03-28 21:23:05 【问题描述】:

我想实现一个分布式身份验证库以在多个项目中使用它。该库应实现 JWT 身份验证方法。代码如下:

jwt.strategy.ts

import ExtractJwt, Strategy from 'passport-jwt';
import PassportStrategy from '@nestjs/passport';
import Injectable from '@nestjs/common';
import JwtPayload, User from './interfaces';
import ConfigService from "./config.service";

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') 
  constructor(private readonly configService: ConfigService) 
    super(
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: configService.get('secretOrPrivateKey'),
    );
  

  async validate(payload: JwtPayload): Promise<User> 
     return 
      uuid: payload.uuid,
      email: payload.email,
    
  

jwt.auth.module.ts:

import Module, DynamicModule from '@nestjs/common';
import JwtModule from '@nestjs/jwt';
import JwtStrategy from './jwt.strategy';
import PassportModule from '@nestjs/passport';
import ConfigService from "./config.service";
import JwtOptions from "./interfaces/jwt.options";

@Module(
)

export class JwtAuthModule 
  static forRoot(jwtOptions): DynamicModule 
    return 
      module: JwtAuthModule,
      imports: [
        // JwtModule.register(jwtOptions),
        // PassportModule.register(defaultStrategy: 'jwt'),
      ],
      providers: [
        JwtStrategy,
        
          provide: ConfigService,
          useValue: new ConfigService(jwtOptions),
        
      ],
      exports: [ConfigService, JwtStrategy]
    ;
  

我已经在我的app.module.ts 中导入了这个:

import  Module, NestModule, HttpModule  from '@nestjs/common';
import  MongooseModule  from '@nestjs/mongoose';
import  environment  from './environments';
import  AuthModule  from './auth/auth.module';
import  PermissionModule  from './permission/permission.module';
import JwtAuthModule from '@pe/nest-kit';
import JwtModule from '@nestjs/jwt';
import PassportModule from '@nestjs/passport';

@Module(
  imports: [
    JwtModule.register(environment.jwtOptions),
    PassportModule.register(defaultStrategy: 'jwt'),
    JwtAuthModule.forRoot(environment.jwtOptions),
    HttpModule,
    AuthModule,
    PermissionModule,
    MongooseModule.forRoot(environment.mongodb),
  ],
)
export class ApplicationModule implements NestModule 
  configure() 
  

但是,每次我尝试打开项目 url 时,都会出现错误:

[Nest] 27645 - 24.10.2018, 15:23:26 [ExceptionsHandler] 未知 身份验证策略“jwt”+4119ms 错误:未知身份验证 策略“jwt” 尝试(/home/user/workspace/permissions/node_modules/passport/lib/middleware/authenticate.js:187:37) 在进行身份验证(/home/user/workspace/permissions/node_modules/passport/lib/middleware/authenticate.js:363:7) 在 Promise (/home/user/workspace/permissions/node_modules/@nestjs/passport/dist/auth.guard.js:83:3) 在新的承诺 () 在/home/user/workspace/permissions/node_modules/@nestjs/passport/dist/auth.guard.js:75:83 在 MixinAuthGuard。 (/home/user/workspace/permissions/node_modules/@nestjs/passport/dist/auth.guard.js:47:36) 在 Generator.next () 在/home/user/workspace/permissions/node_modules/@nestjs/passport/dist/auth.guard.js:19:71 在新的承诺 () 在 __awaiter (/home/user/workspace/permissions/node_modules/@nestjs/passport/dist/auth.guard.js:15:12) 在 MixinAuthGuard.canActivate (/home/user/workspace/permissions/node_modules/@nestjs/passport/dist/auth.guard.js:40:20) 在 GuardsConsumer.tryActivate (/home/user/workspace/permissions/node_modules/@nestjs/core/guards/guards-consumer.js:13:34) 在 canActivateFn (/home/user/workspace/permissions/node_modules/@nestjs/core/router/router-execution-context.js:97:59) 在 /home/user/workspace/permissions/node_modules/@nestjs/core/router/router-execution-context.js:47:37 在 /home/user/workspace/permissions/node_modules/@nestjs/core/router/router-proxy.js:8:23 在 Layer.handle [as handle_request] (/home/user/workspace/permissions/node_modules/express/lib/router/layer.js:95:5)

我做错了什么?

【问题讨论】:

【参考方案1】:

请在您的模块中添加 JwtStrategy 作为提供者

@Module(
   imports: [...],
   providers: [JwtStrategy],
)

https://docs.nestjs.com/techniques/authentication

【讨论】:

【参考方案2】:

我通过安装@types/passport 解决了这个问题。使用 NestJS、TypeScript 和 JWT。

【讨论】:

【参考方案3】:

尝试在您的模块中添加JwtStrategy 作为提供者:

@Module(
  imports: [
   ....
  ],
  providers: [JwtStrategy],
)

再试一次!

【讨论】:

【参考方案4】:

解决了。 在 php 中,我们为整个项目创建了一棵依赖树。在 npm 中,每个包都有自己的依赖子树,例如。 g.: --护照 --@pe/nest-kit ----护照 nest-kit 使用来自----passport 的对象,但根项目使用同名类型的对象,但实际上这是 nodejs 编译器的另一种类型。解决办法是通过@pe/nest-kit从@nestjs/passport重新导出AuthGuard,就可以了。

【讨论】:

【参考方案5】:

这是我在 github 中的代码:https://github.com/riadhriadh/prototype_nestjs/tree/dev

在 jwt.strategy.ts 中

    import * as passport from 'passport';
    import  ExtractJwt, Strategy  from 'passport-jwt';
    import  Injectable  from '@nestjs/common';
    import  AuthService  from '../auth.service';
    const  config_projet =require("./projet_config");
    @Injectable()
    export class JwtStrategy extends Strategy 
      constructor(private readonly authService: AuthService) 
        super(
          
            jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
            passReqToCallback: true,
            secretOrKey: config_projet.secret,
          ,
          async (req, payload, next) => await this.verify(req, payload, next)
        );
        passport.use(this);
      

      public async verify(req, payload, done) 
        const isValid = await this.authService.validateUser(payload);
        if (!isValid) 
          return done('Unauthorized', false);
        
        done(null, payload);
      

====================

在:auth.service.ts

import  Injectable  from '@nestjs/common';
import * as jwt from 'jsonwebtoken';
import  UsersService  from 'users/users.service';
const  config_projet =require("../projet_config");
var fs = require('fs');
@Injectable()
export class AuthService 

  constructor(private readonly usersService: UsersService)  


  async createToken(email: string) 
    const expiresIn = 6000 * 60;
    const secretOrKey = fs.readFileSync("./key.pem");;
    const user =  email ;

     const token = jwt.sign(user, secretOrKey,    audience: 'urn:foo' );


    return  expires_in: expiresIn, token ;
  
  async validateUser(signedUser): Promise<boolean> 
    if (signedUser && signedUser.email) 
      return Boolean(this.usersService.getUserByEmail(signedUser.email));
    

    return false;
  

===============================

在:auth.controller.ts

=================================

import  Controller, Post, HttpStatus, HttpCode, Get, Response, Body  from '@nestjs/common';
import  AuthService  from './auth.service';
import  UsersService  from 'users/users.service';
import  User  from 'users/user.entity';

@Controller("auth")
export class AuthController 
    constructor(
        private readonly authService: AuthService,
        private readonly userService: UsersService
    ) 
    @Post('login')
    async loginUser(@Response() res: any, @Body() body: User) 
      if (!(body && body.email && body.password)) 
        return res.status(HttpStatus.FORBIDDEN).json( message: 'Email and password are required!' );
      

      const user = await this.userService.getUserByEmail(body.email);

      if (user) 
        if (await this.userService.compareHash(body.password, user.password)) 
          return res.status(HttpStatus.OK).json(await this.authService.createToken(user.email));
        
      

      return res.status(HttpStatus.FORBIDDEN).json( message: 'Email or password wrong!' );
     
    @Post('register')
    async registerUser(@Response() res: any, @Body() body: User) 
      if (!(body && body.email && body.password && body.last_name && body.first_name)) 
        return res.status(HttpStatus.FORBIDDEN).json( message: 'Username and password are required!' );
      

      let user = await this.userService.getUserByEmail(body.email);

      if (user) 
        return res.status(HttpStatus.FORBIDDEN).json( message: 'Email exists' );
       else 
        let userSave = await this.userService.create(body);
       if(userSave)
         body.password=undefined;
       
        return res.status(HttpStatus.OK).json(userSave);
      
    

【讨论】:

欢迎来到 *** 并感谢 y9ou 的回答。请为提问者和未来的研究人员提供一个解释,以便人们可以从您提供的内容中学习,而不是在不理解的情况下复制解决方案。【参考方案6】:

你确定你已经添加了所有需要的包吗?尝试阅读身份验证文档https://docs.nestjs.com/techniques/authentication,它很好地解释了如何处理 JWT。

【讨论】:

您好,这并不能真正回答问题。当您有足够的声誉时,您就可以对帖子发表评论以要求澄清。

以上是关于NestJS jwt-passport 身份验证的主要内容,如果未能解决你的问题,请参考以下文章

使用电子邮件进行身份验证时,NestJS 护照身份验证返回 401

NestJs JWT 身份验证返回 401

Nest.js 中使用 @nestjs/passport 的可选身份验证

NestJS - 错误:未知的身份验证策略“本地”

NestJs 使用 jwt 和私钥和公钥进行身份验证

nestjs swagger 是不是支持 cookie 身份验证?