在没有 AuthGuard 的路由上获取 nestjs 中的当前用户

ZVE*_*R3D 3 node.js typescript passport.js nestjs nestjs-passport

我使用带有 jwt 策略的带护照的 Nestjs。我想根据我的一些请求获得当前用户。目前,我有一个看起来像这样的装饰器:

import { createParamDecorator, ExecutionContext } from '@nestjs/common';

export const CurrentUser = createParamDecorator(
  (data: string, ctx: ExecutionContext) => {
    const user = ctx.switchToHttp().getRequest().user;

    if (!user) {
      return null;
    }

    return data ? user[data] : user; // extract a specific property only if specified or get a user object
  },
);
Run Code Online (Sandbox Code Playgroud)

当我在带有 AuthGuard 的路线上使用它时,它按预期工作:

@Get('test')
  @UseGuards(AuthGuard())
  testRoute(@CurrentUser() user: User) {
    console.log('Current User: ', user);
    return { user };
  }
Run Code Online (Sandbox Code Playgroud)

但是我如何让它在非保护路线上工作(获取当前用户)?我需要用户无论是否获得授权都能够发表他们的评论,但是,当他们登录时,我需要得到他们的名字。

基本上,我需要一种方法来在每个(或至少在一些不是 AuthGuard 的请求上)传播 req.user,通过应用护照中间件在 express 中做真的很简单,但我不知道该怎么做它与@nestjs/passport。

[编辑] 感谢 vpdiongzon 为我指明了正确的方向,我选择根据他的回答制作一个守卫,这只是用 user 或 null 填充 req.user :

import { Injectable } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';

@Injectable()
export class ApplyUser extends AuthGuard('jwt') {
  handleRequest(err: any, user: any) {
    if (user) return user;
    return null;
  }
}
Run Code Online (Sandbox Code Playgroud)

现在我可以在需要获取当前用户的任何未受保护的路线上使用它

@Get('me')
@UseGuards(ApplyUser)
me(@CurrentUser() user: User) {
  return { user };
}
Run Code Online (Sandbox Code Playgroud)

小智 6

无论如何,您都需要将 AuthGuard 应用于每条路线,但如果您有一条不需要身份验证的路线,只需添加一个自定义装饰器,例如:

Auth Guard

export class JwtAuthGuard extends AuthGuard('jwt') {
  constructor(private readonly reflector: Reflector) {
    super();
  }

  handleRequest(err, user, info, context) {
    const request = context.switchToHttp().getRequest();       

    const allowAny = this.reflector.get<string[]>('allow-any', context.getHandler());
    if (user) return user;
    if (allowAny) return true;
    throw new UnauthorizedException();
  }
}
Run Code Online (Sandbox Code Playgroud)

全局应用 app.module.js 中的 AuthGuard

import { APP_GUARD, Reflector } from '@nestjs/core';
import { AppController } from './app.controller';
import { JwtAuthGuard } from './app.guard';



@Module({
  imports: ],
  controllers: [AppController],
  providers: [
    {
      provide: APP_GUARD,
      useFactory: ref => new JwtAuthGuard(ref),
      inject: [Reflector],
    },
    AppService,
  ],
})
export class AppModule {
}
Run Code Online (Sandbox Code Playgroud)

允许无需身份验证的路由的自定义装饰器

import { SetMetadata } from '@nestjs/common';

export const AllowAny = () => SetMetadata('allow-any', true);
Run Code Online (Sandbox Code Playgroud)

在路由中应用 AllowAny,如果 AllowAny 装饰器没有附加在控制器路由中,它将需要一个用户。

  @Post('testPost')
  @AllowAny()
  async testPost(@Req() request) {
    console.log(request.user)
  }
Run Code Online (Sandbox Code Playgroud)