如何在 Nest JS 的服务中获取 req.user [英] Howto get req.user in services in Nest JS
问题描述
在控制器中,我添加了带有守卫的用户对象,注入一些服务并调用该服务以获得一些响应.为简洁起见,我删除了很多代码.
In a controller, I add the user object with a guard, inject some service and call that service to get some response. I have removed a lot of code for brevity.
@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
路由之前已登录.
Since I have the AuthGuard
, I now know the user is logged in before entering :id
route.
在服务中我会做类似的事情
In the service I would do something like
@Injectable()
export class UsersService {
async findOne(id: number): Promise<User> {
return await this.usersRepository.findOne({where: {id: id}});
}
}
当然,我们想要检查登录用户是否可以访问它正在查询的用户.现在的问题是如何获取当前登录的用户.我可以将它作为参数从控制器发送,但由于很多后端需要对当前用户进行安全检查,我不确定这是一个好主意.
But of course we want to have some checks that the logged in user has access to the user it is querying. The question is now how do I get the current logged in user. I can send it as a parameter from the controller, but since a lot of the backend would need security checked on the current user, I'm not sure that is a good idea.
@Get(':id)
async findOne(@Param('id') id, @Req() req: any) {
return await this.userService.findOne(id, req.user);
}
理想情况下,这不起作用,我可以在 UserService 中获取它:
Ideally, which doesn't work, I would be able to get it in the 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
构造函数中注入
Or perhaps through injection in the UserService
constructor
constructor(@Inject(REQUEST_OBJECT) private readonly req: any) {}
那么,有没有比每次函数调用都发送请求对象更好的方式通过后端发送用户对象?
So, is there a better way to send the user object through the backend than always sending the request object in each function call?
推荐答案
2019 年 3 月更新
从 v6 版本开始,您现在可以将 request
对象注入到 请求范围的提供程序:
import { REQUEST } from '@nestjs/core';
import { Request } from 'express';
@Injectable({ scope: Scope.REQUEST })
export class UsersService {
constructor(@Inject(REQUEST) private readonly request: Request) {}
}
<小时>
过时的答案
无法将用户(或请求)直接注入到服务中.Nest.js 尚不支持请求范围的提供程序.这可能会随着版本 6 发生变化.在此之前,服务对请求一无所知.
Outdated answer
It's not possible to inject the user (or request) directly into the service. Nest.js does not yet support request-scoped providers. This might change with version 6. Until then, a service does not know anything about a request.
您可以创建一个自定义装饰器 @User
.使用装饰器比注入请求对象更可取,因为这样会失去很多 nest 的优势(比如 inceptors 和异常过滤器).
You can create a custom decorator @User
. Using a decorator is preferable over injecting the request object because then a lot of nest's advantages get lost (like inceptors and exception filters).
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);
}
角色
您可以创建一个 RolesGuard
以确保登录用户具有所需的角色.有关详细信息,请参阅此答案.
Roles
You can create a RolesGuard
that makes sure the logged in user has the required roles. For details, see this answer.
这篇关于如何在 Nest JS 的服务中获取 req.user的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!