NestJS-如何通过jwt服务创建包装服务(来自jwt模块)

时间:2020-08-29 05:07:21

标签: jwt nestjs nestjs-jwt

对不起,我的英语不好,我来自乌克兰:) 您能否告诉我如何创建我自己的服务,该服务是npm包中jwt模块提供的Jwt服务的扩展?我想为捕获错误创建自己的JwtService,并隔离重复的逻辑以进行令牌创建和验证。请帮我怎么做。随附代码示例。

import { BadRequestException, Injectable } from '@nestjs/common';
import { JwtService as NestJwtService, JwtVerifyOptions } from '@nestjs/jwt';

@Injectable()
export class OwnJwtService extends NestJwtService {
  constructor() {
    super({});
  }

  async verifyAsync<T>(token: string, options?: JwtVerifyOptions): Promise<T> {
    try {
      const res = await super.verifyAsync(token, options);
      console.log('res', res);
      return res;
    } catch (error) {
      // My own logic here ...
      throw new BadRequestException({
        error,
        message: 'Error with verify provided token',
      });
    }
  }
}

或者也许我需要将nestjs jwt服务注入到我自己的服务中?例如:

import { BadRequestException, Injectable } from '@nestjs/common';
import { JwtService as NestJwtService, JwtVerifyOptions } from '@nestjs/jwt';

@Injectable()
export class OwnJwtService {
  constructor(private readonly jwtService: NestJwtService) {}

  async verifyAsync<T>(token: string, options?: JwtVerifyOptions): Promise<T> {
    try {
      const res = await this.jwtService.verifyAsync(token, options);
      console.log('res', res);
      return res;
    } catch (error) {
      throw new BadRequestException({
        error,
        message: 'Error with verify provided token',
      });
    }
  }
}

import { JwtModule as NestJwtModule } from '@nestjs/jwt';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { Module } from '@nestjs/common';

import { OwnJwtService } from 'src/modules/jwt/jwt.service';

@Module({
  imports: [
    NestJwtModule.registerAsync({
      imports: [ConfigModule],
      useFactory: async (configService: ConfigService) => ({
        signOptions: {
          expiresIn: process.env.JWT_EXPIRES_IN,
        },
        secret: process.env.JWT_SECRET,
        secretOrPrivateKey: process.env.JWT_SECRET,
      }),
      inject: [ConfigService],
    }),
  ],
  providers: [OwnJwtService],
  exports: [OwnJwtService],
})
export class JwtModule {}

但这对我不起作用,并且我有类似的错误:

错误:Nest无法解析OwnJwtService(?)的依赖项。请确保在AuthModule上下文中索引[0]处的参数JwtService可用。

1 个答案:

答案 0 :(得分:0)

首先,请注意,JwtModule基本上是基于jsonwebtoken创建一个模块的,您的自定义错误并非要在其中处理。

第二,当您使用 registerAsync 时,您应该使用configService.get('JWT_SECRET')中的ConfigService获取ENV变量。

第三,您的问题效率低下。 JwtModule已经可以满足您的所有需求。您只需要实现它。同样,只要将其视为适用于Nest的jsonwebtoken软件包即可。就是这样。

在注册时,登录和刷新令牌(如果存在)会在您创建新令牌时路由sign。 在您的请求中间件中,您verify

Nest的一大问题是其文档。它没有您需要的一切。验证路由的方法可能不止一种,但最直接的方法就是使用Express中间件,就像在典型的Express应用中一样。

为此,您需要像这样在AppModule中实现它:

@Module(...)
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer): MiddlewareConsumer | void {
    consumer.apply(cookieParser(), AuthMiddleware).forRoutes('/');
  }
}

在此示例中,我还将注册模块cookieParser(),因为我将令牌发送到cookie中。其他cookie模块也可以。 NestModule和MiddlewareConsumer都来自@ nestjs / common。

AuthMiddleware是我使用此框架制作的中间件...

export class AuthMiddleware implements NestMiddleware {
  constructor(
    private readonly configService: ConfigService,
    private readonly jwtService: JwtService
  ) {}

  async use(req: Request, res: Response, next: NextFunction) {
    const { yourJwtToken } = req.cookies;
    const isValidToken = this.jwtService.verify(
      yourJwtToken,
      this.configService.get('JWT_SECRET'),
    );

    if (!isValidToken) throw new UnauthorizedException();

    // etc...

    next();
  }
}

最后,您可能要问的是应用AuthGuard。

如果您使用Passport,则只需遵循文档以应用它们。如果您,他们已经抛出了错误。如果要更改它,只需重写其方法即可。

您也可以手动执行。只需使用控制台生成防护,就可以在其中检查身份验证context.switchToHttp().getRequest()并在检查凭据后返回布尔值,并根据需要使用构造函数检查权限。

如果愿意,您也可以从上方跳过中间件配置,并在防护装置内实现逻辑。

再次,我真的不认为更改JwtModule在这里是最好的主意。