我将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 };
}
答案 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)
}