You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NestJS角色权限控制报错:dadosCorretora.roles未定义

权限控制报错解决及实体字段疑问

问题背景

开发项目时需实现管理员(Admin)和普通用户(Normal)的权限控制:仅管理员可执行新增数据操作,普通用户无此权限。但当前运行时报错:

ERROR [ExceptionsHandler] Cannot read properties of undefined (reading 'roles')
报错位置为RolesGuardGuard中的dadosCorretora.roles(非实体文件中的roles字段)。

相关代码

1. 角色枚举(data.roles)

export enum Role {
  Normal = 'normal',
  Admin = 'admin',
}

2. Roles装饰器(roles.ts)

/* eslint-disable prettier/prettier */
import { SetMetadata } from '@nestjs/common';
import { Role } from './data.roles';

export const ROLES_KEY = 'roles';
export const Roles = (...roles: Role[]) => SetMetadata(ROLES_KEY, roles);

3. Roles守卫(roles guard.ts)

/* eslint-disable prettier/prettier */
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Observable } from 'rxjs';
import { Role } from '../../P.Roles/data.roles';
import { ROLES_KEY } from '../../P.Roles/roles.decorator';

@Injectable()
export class RolesGuardGuard implements CanActivate {
  constructor(private reflector: Reflector){}
  canActivate(
    contexto: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    const requiredRoles = this.reflector.getAllAndOverride<Role[]>(ROLES_KEY, [
      contexto.getHandler(),
      contexto.getClass()
    ])

    if(!requiredRoles){
      return true
    }

    const {dadosCorretora} = contexto.switchToHttp().getRequest()

    return requiredRoles.some((role) => dadosCorretora.roles?.includes(role))
  }
}

4. DadosCorretora实体文件

/* eslint-disable prettier/prettier */
import {
  Column,
  CreateDateColumn,
  DeleteDateColumn,
  Entity,
  ManyToOne,
  PrimaryGeneratedColumn,
  UpdateDateColumn,
} from 'typeorm';
import { CorretoraEntity } from '../corretora/corretora.entity';
import { Exclude } from 'class-transformer';
import { Role } from '../P.Roles/data.roles';
@Entity({ name: 'dadosCorretora' })
export class DadosCorretoraEntity {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column({ name: 'ceo', nullable: false })
  ceo: string;
  
  @Exclude()
  @Column({ name: 'senha', nullable: false })
  senha: string;

  @Column({ name: 'email', nullable: false })
  email: string;

  @Column({type: 'enum', enum: Role, default: Role.Normal})
  roles: string[];
}

5. 使用守卫的接口代码

@Post('/:id')
@Roles(Role.Admin)
@UseGuards(RolesGuardGuard)
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async create(@Param('id') id: string, @Body() {senha, ...dados}: criarDadosDTO, @Body('senha', HashearSenha) senhaHash: string) {
  const dados2 = await this.dadosCorretoraService.criarDadosC(id, {
    senha: senhaHash,
    ...dados
  })

  return {
    Messagem: `Dados criados para a corretora ${id}`,
    Dados: dados2
  }
}

请求示例

{
    "ceo": "Polsen",
    "senha": "polsen2244GIGANTIC",
    "email": "pol@gmail.com",
    "roles": "admin"
}

报错解决及字段疑问解答

1. 核心报错解决:dadosCorretora未挂载到请求对象

报错的直接原因是contexto.switchToHttp().getRequest()中不存在dadosCorretora属性,导致读取dadosCorretora.roles时触发undefined错误。

  • 必须先实现认证逻辑:比如通过JWT守卫完成用户登录验证,解析token后查询对应的DadosCorretoraEntity实例,将其挂载到请求对象的dadosCorretora字段上。
  • 临时调试兼容:如果还未实现认证,可先做空值兜底避免报错:
    const { dadosCorretora } = contexto.switchToHttp().getRequest() || {};
    return requiredRoles.some((role) => dadosCorretora?.roles?.includes(role));
    

2. 实体roles字段的配置修正

当前实体中roles字段定义存在类型不匹配问题:

@Column({type: 'enum', enum: Role, default: Role.Normal})
roles: string[];
  • type: 'enum'对应单个枚举值,但字段类型声明为string[](数组),会导致数据库存储和实体映射异常。
  • 修正方案二选一:
    // 方案1:支持多角色,存储为逗号分隔字符串
    @Column({type: 'simple-array', enum: Role, default: [Role.Normal]})
    roles: Role[];
    
    // 方案2:仅支持单角色
    @Column({type: 'enum', enum: Role, default: Role.Normal})
    roles: Role;
    
  • 对应请求示例:如果用多角色类型,roles需传数组格式["admin"]。

3. 实体是否需要roles字段

必须添加roles字段,这是权限控制的核心标识,用来区分用户角色类型。你当前的实体已定义该字段,只需修正上述类型匹配问题即可。

额外优化建议

  • 守卫类名改为RolesGuard(去掉重复的Guard后缀),符合NestJS命名规范
  • 接口需同时使用认证守卫和角色守卫,确保先完成身份认证再做权限校验:
    @Post('/:id')
    @Roles(Role.Admin)
    @UseGuards(AuthGuard('jwt'), RolesGuardGuard)
    async create(...) { ... }
    

内容的提问来源于stack exchange,提问作者user22358808

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 14:00:32