无法从我的 RoleGuard、nestJS 中检索 request.user



我正在设计一个用于特殊控制器的角色保护。我遵循文档的方法在app.module级别全局使用它。这是代码。

async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.enableCors();
app.useGlobalGuards(new RoleGuard(new Reflector()));
await app.listen(3000);
}

现在,我的RoleGuard的Code工作正常,并在预期的时候返回console.log结果,只是应该由passport中间件添加的request.user不存在。这是警卫的代码:

export class RoleGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
const roles = this.reflector.get<string[]>('roles', context.getHandler());
if (!roles) {
console.log('no roles');
return true;
}
const request = context.switchToHttp().getRequest();
const user = request.user;
console.dir(user);
return this.matchRoles(roles, user);
}

console.dir显示未定义,但当尝试console.dr请求时,它工作正常,只是它不包含用户属性。

听起来你已经解决了自己的问题,AuthGuard需要在RolesGuard之前运行。原因是passport负责设置req.user属性,因此AuthGuard(在后台使用passport(需要首先运行。所有Nest增强器都有一个定义的运行顺序,如请求生命周期页面中所记录的。首先运行全局增强子(通过app.useGlobal*()APP_*结合的增强子(。然后是控制器级增强器,最后是方法级增强器。

为了允许全局设置RolesGuard,您可以创建一个保护extends AuthGuard(),并读取一些关于AuthGuard是否应该触发的自定义元数据。如果元数据存在,则返回true作为短路,如果不存在,则在自定义保护的canActivate方法中返回super.canActivate()。您可以设置此元数据,类似于设置角色元数据的方式,也在文档中概述。

将控制器下的Guard Decorator从main.ts移开,现在可以正确显示request.user对象。我假设passport中间件稍后会附加用户属性,因此它在应用程序的全局级别上是看不见的。我希望对这个问题有更多的了解,因为这只是我自己的假设

您可以尝试以下代码片段,它与您的代码几乎相似,所以我给出了整个片段:

@Injectable()
export class RolesGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
// get the role of the request
const roles = this.reflector.get<Role[]>("roles", context.getHandler());
if (!roles) {
return true;
}
// now get the current user
const request = context.switchToHttp().getRequest();
const requestData = request;
return roles.some((role) => requestData.user.role.toLowerCase() === role);
}
}

对于我的案例,Role[]来自用户模型的userRole。这是我的用例:

export enum Role {
ADMIN = "admin",
USER = "user",
}

你需要从你的代码库中导入它。

最新更新