4

有人知道我在哪里可以看到 AuthGuard('jwt') 中的 canActivate 方法的完整代码吗?我意识到 canActivate 方法通过使用 console.log() 调用 JwtStrategy validate 方法,如下所示:

// jwt.strategy.ts

@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(
    private readonly configService: ConfigService,
    private readonly usersService: UsersService,
  ) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      ignoreExpiration: true,
      secretOrKey: configService.get<string>('JWT_SECRET'),
    });
  }

  async validate(payload: any) {
    try {
      const user = await this.usersService.getUserById(payload.id);
      // console.log is here
      console.log(user);
      return user;
    } catch (e) {
      console.log(e);
      return null;
    }
  }
}

如果我使用原始的 canActivate 方法,则会调用 console.log。我认为 JwtStrategy 是一个中间件,所以只要有请求就会调用 validate 方法。但是,当我尝试覆盖 canActivate 方法以添加授权时,不会调用 JwtStrategy validate 方法中的 console.log:

// jwt-auth.guard.ts

import { ExecutionContext, Injectable } from '@nestjs/common';
import { GqlExecutionContext } from '@nestjs/graphql';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {
  getRequest(context: ExecutionContext) {
    const ctx = GqlExecutionContext.create(context);
    return ctx.getContext().req;
  }

  canActivate(context: ExecutionContext): boolean {
    try {
      // Override: handle authorization
      // return true or false
      // Should JwtStrategy.validate(something) be called here?
    } catch (e) {
      console.log(e);
      return false;
    }
  }
}

然后我试图找到 AuthGuard('jwt') 的原始代码以了解其逻辑,但我无法做到。任何帮助将不胜感激,谢谢!

4

1 回答 1

5

好的,所以这将是一个非常有趣的深入研究。系好安全带。

Middleware因为在 NestJS 中仍然存在 express 方法;也就是说,这不是 Express 中间件意义上的普通中间件。正如您所提到AuthGuard()#canActivate()的,最终会调用适当的PassportStrategy. 这些策略在被调用的第 40-41 行特别注册在这里。这注册了要用于passport.use()的护照策略类的方法。大多数底层逻辑非常抽象,阅读时可能会丢失上下文,因此请花点时间了解类、mixin(返回类的函数)和继承的概念。validatepassport.verify()

AuthGuard 的第 51 行passportFn最初创建的地方,并且在这个passportFn passport.authenticate中被调用(它passport.verify在它的引擎盖下调用)(阅读 Passport 的代码更加令人困惑,所以我会让你在需要的时候运行它)。

如果您想为您的canActivate()方法添加一些额外的逻辑,您可以最终调用super.canActivate(context)以调用最终调用的原始canActivate()方法,passport.authenticate()因此<Strategy>#validate. 这可能看起来像

@Injectable()
export class CustomAuthGuard extends AuthGuard('jwt') {

  async canActivate(context: ExecutionContext): Promise<boolean> {
    // custom logic can go here
    const parentCanActivate = (await super.canActivate(context)) as boolean; // this is necessary due to possibly returning `boolean | Promise<boolean> | Observable<boolean>
    // custom logic goes here too
    return parentCanActivate && customCondition;
  }
}
于 2021-01-04T03:51:06.730 回答