如何在Nestjs中获取服务中的req.user

问题描述 投票:1回答:1

在控制器中,我添加了一个带有防护的用户对象,注入一些服务并调用该服务以获得一些响应。为简洁起见,我删除了很多代码。

@Controller()
@UseGuards(AuthGuard())
export class UserController() {
   constructor(private readonly userService: UsersService) {
   }

   @Get(':id')
   async findOne(@Param('id') id) {
      return await this.userService.findOne(id);
   }
}

由于我有AuthGuard,我现在知道用户在进入:id路线之前已登录。

在服务中我会做类似的事情

@Injectable()
export class UsersService {
   async findOne(id: number): Promise<User> {
      return await this.usersRepository.findOne({where: {id: id}});
   }
}

但是我们当然希望进行一些检查,登录用户可以访问它正在查询的用户。现在的问题是如何获得当前登录的用户。我可以从控制器发送它作为参数,但由于很多后端需要在当前用户上检查安全性,我不确定这是个好主意。

@Get(':id)
async findOne(@Param('id') id, @Req() req: any) {
   return await this.userService.findOne(id, req.user);
}

理想情况下,哪些不起作用,我将能够在UserService中获取它:

async findOne(id: number, @Req req: any): Promise<User> {
   if (id === req.user.id || req.user.roles.contains('ADMIN')) {
      return await this.userRepository.findOne({where: {id: id}});
   }
}

或者也许通过注入UserService构造函数

constructor(@Inject(REQUEST_OBJECT) private readonly req: any) {}

那么,是否有更好的方法通过后端发送用户对象,而不是总是在每个函数调用中发送请求对象?

javascript node.js typescript nestjs
1个回答
4
投票

Update March 2019

从版本v6开始,您现在可以将request对象注入请求范围的提供程序:

@Injectable({ scope: Scope.REQUEST })
export class UsersService {
  constructor(@Inject(REQUEST) private readonly request: Request) {}
}

Outdated answer

将用户(或请求)直接注入服务是不可能的。 Nest.js尚不支持请求范围的提供程序。这可能会随着版本6的变化而变化。在此之前,服务对请求一无所知。

Logged in user

你可以创建一个custom decorator @User。使用装饰器比注入请求对象更好,因为很多嵌套的优点都会丢失(比如接收器和异常过滤器)。

export const User = createParamDecorator((data, req) => {
  return req.user;
});

然后像这样使用它:

@UseGuards(AuthGuard()) 
@Get(':id)
async findOne(@Param('id') id, @User() user) {
   return await this.userService.findOne(id, user);
}

Roles

您可以创建一个RolesGuard,以确保登录用户具有所需的角色。有关详细信息,请参阅此answer

© www.soinside.com 2019 - 2024. All rights reserved.