使用Nestjs实现基于JWT + RBAC的认证授权系统

前言

这篇文章使用Nestjs实现了一个基于JWT+RBAC(Role-Based Access Control)的认证授权系统,主要包含以下功能:

  • 用户认证:实现用户登录、登出等基础认证功能
  • 权限控制:基于RBAC模型的细粒度权限控制
  • JWT认证:使用JWT实现无状态的用户身份验证

数据库设计

实体关系图

erDiagram SysUsersEntity ||--o{ UsersRoleEntity : has RoleEntity ||--o{ UsersRoleEntity : has SysUsersEntity { number id PK string loginName string password string status number tokenVersion } RoleEntity { number id PK string name } UsersRoleEntity { number admin_id PK number role_id PK }

表结构说明

1. 用户表 (ibuy_admin)

字段名 类型 说明 约束
id number 用户ID 主键
login_name string 登录名 唯一,可空
password string 密码 可空
status string 用户状态 可空
tokenVersion number token版本号 默认值0

2. 角色表 (ibuy_role)

字段名 类型 说明 约束
id number 角色ID 主键
name string 角色名称 唯一,可空

3. 用户角色关联表 (ibuy_admin_role)

字段名 类型 说明 约束
admin_id number 用户ID 联合主键
role_id number 角色ID 联合主键

系统配置

环境变量

需要在.env文件中配置以下环境变量:

env 复制代码
JWT_SECRET=your_jwt_secret_key

核心功能

1. 认证流程

1.1 登录认证

用户登录时,系统会:

  1. 验证用户名和密码
  2. 生成包含用户信息的JWT Token
  3. 返回Token和用户信息
typescript 复制代码
// auth.controller.ts
@Public()
@HttpCode(HttpStatus.OK)
@Post('login')
async signIn(@Body() user: Record<string, any>) {
  return this.authService.signIn(user.loginName, user.password);
}

1.2 JWT认证守卫

系统使用全局AuthGuard进行Token验证:

typescript 复制代码
// auth.guard.ts
@Injectable()
export class AuthGuard implements CanActivate {
  async canActivate(context: ExecutionContext): Promise<boolean> {
    // 检查是否是公开接口
    const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
      context.getHandler(),
      context.getClass(),
    ]);
    if (isPublic) return true;

    // 验证Token
    const request = context.switchToHttp().getRequest();
    const token = this.extractTokenFromHeader(request);
    if (!token) {
      throw new UnauthorizedException();
    }

    try {
      const payload = await this.jwtService.verifyAsync(token);
      request.user = payload;
    } catch {
      throw new UnauthorizedException();
    }
    return true;
  }
}

2. RBAC权限控制

2.1 角色权限守卫

使用PermissionGuard实现基于角色的权限控制:

typescript 复制代码
// permission.guard.ts
@Injectable()
export class PermissionGuard implements CanActivate {
  async canActivate(context: ExecutionContext): Promise<boolean> {
    const request = context.switchToHttp().getRequest();
    if (!request.user) return true;

    // 获取用户角色
    const roleIds = await this.usersRoleService.findRolesIdByUserId(request.user.user_id);
    const roles = await this.roleService.findRolesByRoleIds(roleIds.data);
    const roleNames = roles.data?.map((role) => role.name);

    // 检查权限
    const requiredRoles = this.reflector.getAllAndOverride(PERMISSION_KEY, [
      context.getClass(),
      context.getHandler(),
    ]);

    return requiredRoles?.some((role) => roleNames?.includes(role)) ?? true;
  }
}

2.2 权限装饰器

提供@Permission装饰器用于声明接口所需的角色权限:

typescript 复制代码
// permission.decorator.ts
export const PERMISSION_KEY = 'permission_by_roles';
export const Permission = (...permissions: string[]) =>
  SetMetadata(PERMISSION_KEY, permissions);

3. 使用示例

3.1 接口权限控制

typescript 复制代码
// role.controller.ts
@Permission('admin')  // 声明需要admin角色才能访问
@Controller('role')
export class RoleController {
  @Post()
  createRole(@Body() createRoleDto: CreateRoleDto) {
    return this.roleService.createRole(createRoleDto);
  }
}

3.2 全局配置

在AppModule中注册全局守卫:

typescript 复制代码
// app.module.ts
@Module({
  providers: [
    {
      provide: APP_GUARD,
      useClass: AuthGuard,
    },
    {
      provide: APP_GUARD,
      useClass: PermissionGuard,
    },
  ],
})
export class AppModule {}

注意事项

  1. 所有需要认证的接口都会自动经过AuthGuard验证
  2. 使用@Public()装饰器可以将接口标记为公开接口
  3. 使用@Permission()装饰器可以指定访问接口所需的角色
  4. 角色验证基于RBAC模型,支持多角色
相关推荐
不好听6135 小时前
从一行 JSX 到屏幕像素:前端开发者必须懂的浏览器渲染管线
前端
恒拓高科WorkPlus5 小时前
企业级内网即时通讯建设模型:BeeWorks内网IM四层架构
前端
GetcharZp5 小时前
抛弃低效SSH!这套Ansible+Web可视化神器,让你天天准点下班!
后端
前端小李子6 小时前
前端环境变量裸奔?我用 EnvShield 给它穿了件防弹衣
前端
youtootech6 小时前
HarmonyOS《柚兔学伴》项目实战25-我的页面、Web 嵌入与项目总结
前端·华为·harmonyos
小林ixn6 小时前
从零到一理解 React 父子组件通信:手写一个 Todo 应用带你彻底搞懂单向数据流
前端·javascript·react.js
醇氧8 小时前
CountDownLatch / CyclicBarrier / Semaphore 面试高频问答清单
前端·面试·职场和发展
weixin_446260859 小时前
HACO:面向动态部署环境的对冲式智能计算可靠多智能体调度框架
后端·python·flask
qetfw9 小时前
MXU:Tauri 2 + React 的 MaaFramework 跨平台 GUI 源码
前端·python·react.js·前端框架·开源项目·效率工具