在控制器中,我为用户对象添加了一个防护,并注入了一些服务并调用该服务以获得一些响应。为了简洁起见,我删除了很多代码。
@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) {}
因此,与在每个函数调用中始终发送请求对象相比,有没有比通过后端发送用户对象更好的方法了?
答案 0 :(得分:2)
从v6版本开始,您现在可以将request
对象注入到请求范围的提供程序中:
@Injectable({ scope: Scope.REQUEST })
export class UsersService {
constructor(@Inject(REQUEST) private readonly request: Request) {}
}
不可能将用户(或请求)直接注入服务。 Nest.js尚不支持请求范围的提供程序。版本6可能会更改。在此之前,服务对请求一无所知。
您可以创建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);
}
您可以创建一个RolesGuard
来确保登录的用户具有所需的角色。有关详细信息,请参见此answer。