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

时间:2020-08-05 03:12:33

标签: node.js typescript passport.js nestjs nestjs-passport

我将nestjs与带jwt策略的护照一起使用。我想让我的一些请求成为当前用户。 目前,我有一个看起来像这样的装饰器:

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
  },
);

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

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

但是我如何使其在不受保护的路由上工作(获取当前用户)?无论用户是否经过授权,我都需要他们能够发表他们的评论,但是,当他们登录时,我需要获得他们的名字。

基本来说,我需要一种在每个(或至少在某些未经AuthGuard要求的请求上)传播req.user的方法,通过应用护照中间件来进行快速表达确实是直截了当的,但是我不确定如何用@ 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;
  }
}

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

@Get('me')
@UseGuards(ApplyUser)
me(@CurrentUser() user: User) {
  return { user };
}

1 个答案:

答案 0 :(得分:5)

您需要将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();
  }
}

在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 {
}

自定义装饰器,允许未经身份验证的路由

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

export const AllowAny = () => SetMetadata('allow-any', true);

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

  @Post('testPost')
  @AllowAny()
  async testPost(@Req() request) {
    console.log(request.user)
  }