TypeError:无法读取未定义的 NestJs 的属性“角色”

Gau*_*nec 6 nestjs

如果不是管理员,我会尝试阻止某些 root,但是当我运行代码时,出现 TypeError 但我不知道如何解决它。

谢谢

角色.guards.ts

import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Role } from './role.enums';
import { ROLES_KEY } from './roles.decorator';

@Injectable()
export class RolesGuard implements CanActivate {
  constructor(private reflector: Reflector) {}

  canActivate(context: ExecutionContext): boolean {
    const requiredRoles = this.reflector.getAllAndOverride<Role[]>(ROLES_KEY, [
      context.getHandler(),
      context.getClass(),
    ]);
    if (!requiredRoles) {
      return true;
    }
    const { user } = context.switchToHttp().getRequest();
    return requiredRoles.some((Role) => user.roles?.includes(Role));
  }
}
Run Code Online (Sandbox Code Playgroud)

文章.controller.ts

@UseGuards(JwtAuthGuard)
@Roles(Role.Admin)
async addArticle(
    @Body('title') artTitle: string,
    @Body('description') artDescription: string,
    @Body('url') artUrl: string,
    @Body('cover') artCover: string,
    @Body('content') artContent: string,
    @Body('category') artCategory: string,
){
    const generatedId = await  this.articlesService.insertArticle(
        artTitle,
        artDescription,
        artUrl,
        artCover,
        artContent,
        artCategory
    );
    return { id: generatedId };
  }
Run Code Online (Sandbox Code Playgroud)

当我运行代码时,出现 TypeError 但我不知道如何解决它。

谢谢

小智 7

我想为Jay McDoniel 的答案添加更多细节,因为我仍然花了几个小时来解决这个问题。

  1. 使用以下内容创建JWT.module.ts(JwtModule 已被 @nestjs/jwt 使用,因此我使用 caps)文件:
import { ConfigModule, ConfigService } from "@nestjs/config";
import { JwtModule } from "@nestjs/jwt";

@Module({
    imports: [
      {
        ...JwtModule.registerAsync({
            imports: [ConfigModule],
            useFactory: async (configService: ConfigService) => ({
              secretOrKeyProvider: () => (configService.get<string>("JWT_SECRET")),
              signOptions: {
                  expiresIn: 3600,
              },
            }),
            inject: [ConfigService],
          }),
        global: true
      }
    ],
    exports: [JwtModule]
})
export class JWTModule {}
Run Code Online (Sandbox Code Playgroud)
  1. 将此类添加到您的app.module.ts数组中imports
  2. 如果你有
{
      provide: APP_GUARD,
      useClass: RolesGuard,
},
Run Code Online (Sandbox Code Playgroud)

在您的任何模块中...删除它。在任何提供者中声明守卫将自动使其成为全局的,并且您不希望受到保护的端点最终将受到保护(我知道https://docs.nestjs.com/security/authorization#basic-rbac-implementation告诉你在你的提供者中注册角色守卫,但这对我来说不起作用)。您只需将您的策略​​导入到相关路线即可。

  1. 在你的控制器中,现在应该可以工作了
  @ApiBearerAuth()
  @Roles(Role.Admin)
  @UseGuards(JwtAuthGuard, RolesGuard)
  @Get()
  findAll() {
    return this.usersService.findAll();
  }
Run Code Online (Sandbox Code Playgroud)

因此此端点接受具有有效 JWT 和该 JWT 内的管理员角色的用户。


Jay*_*iel 5

如果我必须打赌,你RolesGuard的绑定到全局范围,而 theJwtAuthGuard绑定到路由处理程序范围。全局守卫首先执行,因此在可以设置RolesGuard之前执行(护照是在幕后执行此操作的)。您可以做的是确保有一个属性(通过中间件或全局运行的jutt),或者您可以在运行后将其范围移动到路由处理程序级别。JwtAuthGaurdreq.userreq.userJwtAuthGuardRolesGuardJwtAuthGuard


小智 -1

在控制器上方使用 @Post()

@UseGuards(JwtAuthGuard)
@Roles(Role.Admin)
@Post('')
async addArticle(
    @Body('title') artTitle: string,
    @Body('description') artDescription: string,
    @Body('url') artUrl: string,
    @Body('cover') artCover: string,
    @Body('content') artContent: string,
    @Body('category') artCategory: string,
){
    const generatedId = await  this.articlesService.insertArticle(
        artTitle,
        artDescription,
        artUrl,
        artCover,
        artContent,
        artCategory
    );
    return { id: generatedId };
  }
Run Code Online (Sandbox Code Playgroud)