1

抱歉我的英语不好,我来自乌克兰 :) 你能告诉我如何创建自己的服务,从 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 (?) 的依赖关系。请确保索引 [0] 处的参数 JwtService 在 AuthModule 上下文中可用。

4

1 回答 1

0

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

其次,当您使用registerAsync时,您的目的是使用 ConfigService 获取 ENV 变量,如configService.get('JWT_SECRET').

第三,你的问题效率低下。JwtModule 已经完成了您需要的一切。你只需要实现它。同样,只需将其视为jsonwebtoken适用于 Nest 的包。而已。

在注册时,登录和 refreshtoken(如果存在)会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 是最好的主意。

于 2020-09-10T00:14:00.857 回答