认证一章和19-auth示例的问题

时间:2019-03-31 12:43:30

标签: nestjs

我下载了19-auth示例,并向其中添加了一些console.log调试代码,然后发现了一些问题。

从不执行JwtAuthGuard中的代码:在以下代码中未将'2222222'打印到控制台:

canActivate(context: ExecutionContext) {
console.log('22222222222');
// add your custom authentication logic here
// for example, call super.logIn(request) to establish a session.
return super.canActivate(context);
}

当我在AuthController中将防护更改为JwtAuthGuard时:

@get('data')
@UseGuards(JwtAuthGuard)
findAll(@Req() req) {
return req.user;
// this route is restricted by AuthGuard
// JWT strategy
}

调用了JwtAuthGuard中的代码,但是在canActivate函数中,我无法从请求中获取用户信息。并且可以在JwtStrategy之前调用canActivate函数?

有人可以解释如何为auth模块执行代码,以及如何在JwtAuthGuard中获取用户信息吗?

在此处粘贴最新代码和控制台日志:

  

JwtStrategy

/**
   * jwt passport 调用validate方法来判断是否授权用户进行接口调用
   * @param payload
   */
  async validate(payload: AuthPayload) {
    Logger.log(`payload is ${JSON.stringify(payload)}`, 'JwtStrategy');
    const user = await this.authService.validateUser(payload.id);
    if (!user) {
      throw new UnauthorizedException('不存在的用户信息');
    }
    return user;
  }
  

JwtAuthGuard

canActivate(context: ExecutionContext) {
    // add your custom authentication logic here
    // for example, call super.logIn(request) to establish a session.
    // this.accessPriv = this.reflector.get<string>('accessPriv', context.getHandler());
    console.log('canActivate executed 111111111111111111');
    return super.canActivate(context);
  }

和控制台日志如下:

canActivate executed 111111111111111111

[Nest] 14080   - 2019-04-01 11:19   [JwtStrategy] payload is {"userName":"fanliang","id":"1","iat":1553772641,"exp":1554377441} +2286ms
it seems that the canActivate() function of JwtAuthGuard executed before the validate() function of JwtStrategy, but the user info was attached to the request after JwtStrategy validate().

我想要的是从自定义AuthGuard的canActivate()中的请求获取用户信息,例如JwtAuthGuard

2 个答案:

答案 0 :(得分:0)

我有一个对我有用的解决方案。 在我自己的逻辑之前调用super.canActivate。
似乎是由它触发的req.user人口。
一个例子:

import { ExecutionContext, Injectable } from "@nestjs/common";
import { AuthGuard } from "@nestjs/passport";
import { Request } from "express";

@Injectable()
export class AuthGuardWithAllowSentry extends AuthGuard("jwt") {
  public async canActivate(context: ExecutionContext) {
    // that code will call the passport jwt
    const origCanActivate = await super.canActivate(context);
    // now we have request.user!


    const http = context.switchToHttp();
    const request = http.getRequest<Request>();

    console.log(request.user)

    if (request.header("X-Sentry-Token") === "blablabla") {
      if (request.method === "GET" && request.path.endsWith(".map")) {
        return true;
      }
    }

    // some random logic
    return request.user.roles.includes("admin")
  }
}

对我来说,它更像是一种变通方法,而不是真实的东西。

答案 1 :(得分:-1)

我同意19-auth示例有点让人困惑。这主要是因为它包含JWTAuthGuard(作为构建自定义防护的参考),但是从未真正使用过。相反,已经设置了普通AuthGuard的原始用法以提供JWT功能。但是,两者后卫都利用JWTStrategy。如果您想更好地理解这一点,可以尝试更新AuthController

  @Get('data')
  @UseGuards(AuthGuard())
  findAll() {
    // this route is restricted by AuthGuard
    // JWT strategy
    return {
      message: 'Successfully passed AuthGuard',
    };
  }

  @Get('custom-jwt')
  @UseGuards(new JwtAuthGuard())
  // this route is restricted by JWTAuthGuard custom
  // JWT strategy
  customJwt() {
    return {
      message: 'Successfully passed JWTAuthGuard',
    };
  }

重要的部分是,为了越过任何一个防护措施,您必须发送带有正确设置为token端点返回的令牌的Authorization标头的请求。

例如:Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InRlc3RAZW1haWwuY29tIiwiaWF0IjoxNTU0MDUyNDczLCJleHAiOjE1NTQwNTYwNzN9.3Q8_FC-qFXk1F4KmMrHVSmmNGPAyHdt2myr5c18_E-U

我发现使用Postman或Insomnia之类的工具来构造请求和设置Header等最简单,但是您也可以使用CURL。为Authorization标头设置有效令牌后,您将可以同时访问受保护端点的。如果在JWTStrategy中放入console.log,您将看到两个保护都最终使用validate方法来正确地检索用户。