Nestjs 角色装饰器:让用户脱离有效负载数据的疯狂行为
Nestjs Roles Decorator: Crazy behaviour with getting user out of payload data
我只是想在 Nestjs 中实现我的角色装饰器。到目前为止一切顺利,直到我想将来自 jwt-token 的有效负载数据的用户与所需角色进行比较。我无法解释这是怎么可能的,但如果我让函数 return 始终为真,则只能从有效负载数据中获取用户和角色。设置条件后,用户未定义。这怎么可能?
这是我的(缩短的)用户控制器,我在其中使用装饰器:
@UseGuards(JwtAuthGuard, RolesGuard)
@Controller('users')
export class UsersController {
constructor(private readonly userService: UserService) {}
private readonly logger = new Logger(LoggingService.name);
@Post('/create')
async create(@Body() createUserDto: CreateUserDto) {
const hashedPassword = await bcrypt.hash(createUserDto.password, 10);
createUserDto.password = hashedPassword
return this.userService.createUser(createUserDto);
}
@Roles(Role.SUPERADMIN)
@Get('/')
showUsers() {
return this.userService.getUsers();
}
这里是角色装饰器,条件为:
import { CanActivate, ExecutionContext, Injectable, Logger } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Observable } from 'rxjs';
import { LoggingService } from 'src/services/logging/logging.service';
import { User } from 'src/user/schemas/user.schema';
import { Role } from '../role.enum';
import { ROLES_KEY } from '../decorators/roles.decorator';
import { Types } from 'mongoose';
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private readonly reflector: Reflector) {}
private readonly logger = new Logger(LoggingService.name);
canActivate(context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean> {
const roles = this.reflector.get<Role[]>(ROLES_KEY, context.getHandler());
// If there is no Roles-Decorator, just pass through
if (!roles) {
return true;
}
this.logger.debug("REQUIRED ROLES: ", roles)
const request = context.switchToHttp().getRequest();
const userRole = request.user?.roles;
const userID = request.user?.sub;
this.logger.debug("ROLES GUARD USER", userID);
this.logger.debug("USER ROLE", userRole);
// Else, check the request header if it matches
if (roles.includes(userRole)) {
return true;
} else { return false }
}
}
日志输出(当我尝试访问路由时):
[Nest] 4460 - 25.11.2021, 18:56:33 DEBUG [LoggingService] REQUIRED ROLES:
[Nest] 4460 - 25.11.2021, 18:56:33 DEBUG [LoggingService] superadmin
[Nest] 4460 - 25.11.2021, 18:56:33 DEBUG [LoggingService] ROLES GUARD USER
[Nest] 4460 - 25.11.2021, 18:56:33 DEBUG [LoggingService] undefined
[Nest] 4460 - 25.11.2021, 18:56:33 DEBUG [LoggingService] USER ROLE
[Nest] 4460 - 25.11.2021, 18:56:33 DEBUG [LoggingService] undefined
但是当我这样做时:
// Else, check the request header if it matches
// if (roles.includes(userRole)) {
// return true;
// } else { return false }
return true;
日志输出是这样的:
[Nest] 39888 - 25.11.2021, 19:00:14 DEBUG [LoggingService] REQUIRED ROLES:
[Nest] 39888 - 25.11.2021, 19:00:14 DEBUG [LoggingService] superadmin
[Nest] 39888 - 25.11.2021, 19:00:14 DEBUG [LoggingService] ROLES GUARD USER
[Nest] 39888 - 25.11.2021, 19:00:14 DEBUG [LoggingService] 619962ad86e412dc06983a0e
[Nest] 39888 - 25.11.2021, 19:00:14 DEBUG [LoggingService] USER ROLE
[Nest] 39888 - 25.11.2021, 19:00:14 DEBUG [LoggingService] superadmin
控制流是从上到下的,对吧?任何帮助将不胜感激!
在任何模块中使用APP_GUARD
,由应用程序注册的任何模块将守卫注册为全局守卫,这将在每个请求之前运行。我要做的是注册两个全局守卫,一个用于 JwtAuthGuard
,一个用于 RolesGuard
,并实现一个 @JwtSkip()
装饰器,告诉 JwtAuthGuard
它可以跳过身份验证在这条路线上(对于 RolesGuard
是一样的,因为它不应该有任何关联的角色
我找到了解决方案!
我没有在全局上下文中注册 RolesGuard。所以我继续把
app.useGlobalGuards(new RolesGuard(new Reflector()));
在main.ts。
然后它突然起作用了。并且我修改了通过守卫的条件如下:
// Else, check the request header if it matches
if (roles.some(r => r == userRole)) {
this.logger.log("ROLES GUARD: PASS")
return true;
} else {
this.logger.error("ROLES GUARD: DENIED")
return false
}
希望对大家有帮助!
我只是想在 Nestjs 中实现我的角色装饰器。到目前为止一切顺利,直到我想将来自 jwt-token 的有效负载数据的用户与所需角色进行比较。我无法解释这是怎么可能的,但如果我让函数 return 始终为真,则只能从有效负载数据中获取用户和角色。设置条件后,用户未定义。这怎么可能?
这是我的(缩短的)用户控制器,我在其中使用装饰器:
@UseGuards(JwtAuthGuard, RolesGuard)
@Controller('users')
export class UsersController {
constructor(private readonly userService: UserService) {}
private readonly logger = new Logger(LoggingService.name);
@Post('/create')
async create(@Body() createUserDto: CreateUserDto) {
const hashedPassword = await bcrypt.hash(createUserDto.password, 10);
createUserDto.password = hashedPassword
return this.userService.createUser(createUserDto);
}
@Roles(Role.SUPERADMIN)
@Get('/')
showUsers() {
return this.userService.getUsers();
}
这里是角色装饰器,条件为:
import { CanActivate, ExecutionContext, Injectable, Logger } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Observable } from 'rxjs';
import { LoggingService } from 'src/services/logging/logging.service';
import { User } from 'src/user/schemas/user.schema';
import { Role } from '../role.enum';
import { ROLES_KEY } from '../decorators/roles.decorator';
import { Types } from 'mongoose';
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private readonly reflector: Reflector) {}
private readonly logger = new Logger(LoggingService.name);
canActivate(context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean> {
const roles = this.reflector.get<Role[]>(ROLES_KEY, context.getHandler());
// If there is no Roles-Decorator, just pass through
if (!roles) {
return true;
}
this.logger.debug("REQUIRED ROLES: ", roles)
const request = context.switchToHttp().getRequest();
const userRole = request.user?.roles;
const userID = request.user?.sub;
this.logger.debug("ROLES GUARD USER", userID);
this.logger.debug("USER ROLE", userRole);
// Else, check the request header if it matches
if (roles.includes(userRole)) {
return true;
} else { return false }
}
}
日志输出(当我尝试访问路由时):
[Nest] 4460 - 25.11.2021, 18:56:33 DEBUG [LoggingService] REQUIRED ROLES:
[Nest] 4460 - 25.11.2021, 18:56:33 DEBUG [LoggingService] superadmin
[Nest] 4460 - 25.11.2021, 18:56:33 DEBUG [LoggingService] ROLES GUARD USER
[Nest] 4460 - 25.11.2021, 18:56:33 DEBUG [LoggingService] undefined
[Nest] 4460 - 25.11.2021, 18:56:33 DEBUG [LoggingService] USER ROLE
[Nest] 4460 - 25.11.2021, 18:56:33 DEBUG [LoggingService] undefined
但是当我这样做时:
// Else, check the request header if it matches
// if (roles.includes(userRole)) {
// return true;
// } else { return false }
return true;
日志输出是这样的:
[Nest] 39888 - 25.11.2021, 19:00:14 DEBUG [LoggingService] REQUIRED ROLES:
[Nest] 39888 - 25.11.2021, 19:00:14 DEBUG [LoggingService] superadmin
[Nest] 39888 - 25.11.2021, 19:00:14 DEBUG [LoggingService] ROLES GUARD USER
[Nest] 39888 - 25.11.2021, 19:00:14 DEBUG [LoggingService] 619962ad86e412dc06983a0e
[Nest] 39888 - 25.11.2021, 19:00:14 DEBUG [LoggingService] USER ROLE
[Nest] 39888 - 25.11.2021, 19:00:14 DEBUG [LoggingService] superadmin
控制流是从上到下的,对吧?任何帮助将不胜感激!
在任何模块中使用APP_GUARD
,由应用程序注册的任何模块将守卫注册为全局守卫,这将在每个请求之前运行。我要做的是注册两个全局守卫,一个用于 JwtAuthGuard
,一个用于 RolesGuard
,并实现一个 @JwtSkip()
装饰器,告诉 JwtAuthGuard
它可以跳过身份验证在这条路线上(对于 RolesGuard
是一样的,因为它不应该有任何关联的角色
我找到了解决方案!
我没有在全局上下文中注册 RolesGuard。所以我继续把
app.useGlobalGuards(new RolesGuard(new Reflector()));
在main.ts。 然后它突然起作用了。并且我修改了通过守卫的条件如下:
// Else, check the request header if it matches
if (roles.some(r => r == userRole)) {
this.logger.log("ROLES GUARD: PASS")
return true;
} else {
this.logger.error("ROLES GUARD: DENIED")
return false
}
希望对大家有帮助!