使用NestJS开发安全API:角色管理 - Auth0

作者:API传播员 · 2026-01-16 · 阅读时间:6分钟
本文详细介绍了使用Auth0和NestJS实现基于角色的访问控制(RBAC)的完整流程,包括在Auth0中创建API权限、角色和用户,以及通过自定义装饰器和保护器在NestJS中集成RBAC,确保API安全性和灵活性。

使用NestJS开发安全API:角色管理

在现代基于角色的访问控制(RBAC),以确保API的安全性和灵活性。


开始之前的准备工作

在开始之前,请确保您已经完成以下步骤:

  1. 克隆项目仓库并切换到指定分支:

    git clone git@github.com:auth0-blog/wab-menu-api-nestjs.git 
    nest-restaurant-api 
    --branch adding-authorization-auth0
  2. 将项目文件夹设置为当前目录,并安装所需依赖项。

  3. 如果尚未设置Auth0应用程序,请参考前面的章节完成相关配置。

  4. 创建一个.env文件,并填入以下内容:

    PORT=7000
    AUTH0_ISSUER_URL="Your Auth0 domain"
    AUTH0_AUDIENCE="Your Auth0 audience"

完成以上步骤后,您即可开始配置基于角色的访问控制。


使用Auth0实现基于角色的访问控制

RBAC是一种根据用户角色分配权限的授权策略。在本教程中,我们将创建一个“菜单管理员”角色,并为其分配特定权限。以下是实现步骤:

1. 创建API权限

在Auth0仪表板中,进入您创建的“菜单API”页面,完成以下操作:

  • 点击“权限”选项卡,添加以下权限:
    • create:items
    • update:items
    • delete:items

接着,进入“设置”选项卡,启用以下选项:

  • 启用RBAC:强制执行基于角色的访问控制。
  • 在访问令牌中添加权限:将权限声明添加到JWT令牌中。

完成后,点击“保存”。

2. 创建角色并分配权限

  1. 在Auth0仪表板中,创建一个名为“菜单管理员”的角色。
  2. 为该角色分配之前创建的权限:
    • 进入角色页面的“权限”选项卡。
    • 选择“菜单API”,并添加所有相关权限。

3. 创建管理员用户

  1. 在Auth0仪表板中,创建一个新用户,例如admin@example.com
  2. 为该用户分配“菜单管理员”角色。

在令牌中添加用户角色

为了让客户端应用程序能够识别用户角色,我们需要使用Auth0规则将角色信息添加到JWT令牌中。

什么是Auth0规则?

Auth0规则是当用户登录时执行的JavaScript函数。您可以使用规则自定义和扩展Auth0的功能。

创建规则

  1. 在Auth0仪表板中,进入“规则”页面并点击“创建规则”。
  2. 选择“空规则”,并命名为“向令牌添加用户角色”。
  3. 替换脚本内容为以下代码:
    function(user, context, callback) {
     const namespace = 'https://menu-api.demo.com';
     if (context.authorization && context.authorization.roles) {
       const assignedRoles = context.authorization.roles;
       if (context.idToken) {
         context.idToken[${namespace}/roles] = assignedRoles;
       }
       if (context.accessToken) {
         context.accessToken[${namespace}/roles] = assignedRoles;
       }
     }
     callback(null, user, context);
    }

此规则会在用户登录时,将其角色信息附加到ID令牌和访问令牌中。


在NestJS中实现基于角色的访问控制

为了在NestJS中实现RBAC,我们将创建一个自定义装饰器和保护器,用于验证用户是否具有访问特定端点的权限。

1. 创建自定义装饰器

运行以下命令创建装饰器文件:

nest generate decorator permissions --no-spec

permissions.decorator.ts文件中添加以下代码:

import { SetMetadata } from '@nestjs/common';

export const Permissions = (...permissions: string[]) =>
  SetMetadata('permissions', permissions);

该装饰器会将权限元数据附加到路由处理程序中。

2. 创建自定义保护器

运行以下命令创建保护器文件:

nest generate guard permissions --no-spec

permissions.guard.ts文件中添加以下代码:

import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';

@Injectable()
export class PermissionsGuard implements CanActivate {
  constructor(private readonly reflector: Reflector) {}  canActivate(context: ExecutionContext): boolean {
    const routePermissions = this.reflector.get(
      'permissions',
      context.getHandler(),
    );
    if (!routePermissions) {
      return true;
    }    const request = context.switchToHttp().getRequest();
    const userPermissions = request.user.permissions;    return routePermissions.every(permission =>
      userPermissions.includes(permission),
    );
  }
}

3. 集成到路由中

打开items.controller.ts文件,更新路由处理程序如下:

import { Controller, Get, Post, Put, Delete, Body, Param, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { Permissions } from '../permissions.decorator';
import { PermissionsGuard } from '../permissions.guard';

@Controller('items')
export class ItemsController {
  @UseGuards(AuthGuard('jwt'), PermissionsGuard)
  @Post()
  @Permissions('create:items')
  create(@Body('item') item: any) {
    // 创建逻辑
  }  @UseGuards(AuthGuard('jwt'), PermissionsGuard)
  @Put()
  @Permissions('update:items')
  update(@Body('item') item: any) {
    // 更新逻辑
  }  @UseGuards(AuthGuard('jwt'), PermissionsGuard)
  @Delete(':id')
  @Permissions('delete:items')
  delete(@Param('id') id: number) {
    // 删除逻辑
  }
}

通过为路由添加@Permissions装饰器和PermissionsGuard保护器,您可以确保只有拥有相应权限的用户才能访问这些端点。


测试RBAC功能

使用非管理员用户测试

  1. 登录非管理员账户。

  2. 使用以下命令尝试创建新项目:

    curl -X POST -H 'Authorization: Bearer YOUR-ACCESS-TOKEN' 
    -H 'Content-Type: application/json' 
    -d '{ "item": { "name": "Coffee", "price": 2.99 } }' 
    http://localhost:7000/items
  3. 您将收到403错误,表示权限不足。

使用管理员用户测试

  1. 登录管理员账户。
  2. 使用相同的命令创建新项目,操作应成功。

总结

通过本教程,您学习了如何使用Auth0和NestJS实现基于角色的访问控制(RBAC)。这种方法不仅提高了API的安全性,还提供了灵活的权限管理机制。接下来,您可以尝试将此应用程序部署到云平台,或集成更多功能,如GraphQLgRPC

原文链接: https://auth0.com/blog/developing-a-secure-api-with-nestjs-adding-role-based-access-control/