@dudousxd/nestjs-authz

中文文档
0.11.0发布于 2026/11/12MITTypeScriptES Module构建来源已验证近 30 天下载 2562

在@nestjs/授权之上的外加:坚持RBAC的政策,@Can 帮助者(byId,角色,权限),一个带有批量检查和特设门的门,超级管理员,查询范围界定.

中文使用文档
文档目录10 节
  1. 安装
  2. 政策(官方)+ @PolicyFor
  3. 角色和权限
  4. 超级管理员
  5. 这个 Gate
  6. 决定
  7. 从0.8移走
  8. 一次移动一个控制器 : unannotated: 'allow'
  9. 外部政策引擎(Cerbos, OPA,.)
  10. 许可证

@dudousxd/nestjs-authz — an Aviary library. Call sign: Falcon.

📖 读取文档  · 部分 飞行员 雀巢生态系统


@dudousxd/nestjs-authz

在NestJS的第一党之上的外加 @nestjs/authorization。 。 。 . 政策, @Can()全球逐一拒绝保护 AuthorizationService 来自 官方软件包:先读其文件。 此套件添加了它没有的:

  • 将非洲区域局视为官方政策数字 : RolePolicy 财务报告和审定财务报表 PermissionPolicy (纸牌, 由TypeORM / MikroORM / 支持的租户范围角色、直接权限、角色来源 Prisma / Drizzle 适配器,每个请求一次取取.
  • 官员的助手 @Can()数字 : byId(Post), (中文(简体) ), roles(...), (中文(简体) ), permission(...), (中文(简体) ), ability(...), (中文(简体) ), staticCanArgs(...); 糖类 @Roles(...) 编号 : @Permission(...)。 。 。 .
  • 一个全球超级管理员 还有一个 外部政策引擎 (Cerbos, OPA,...):扩展 AuthzPolicy。 。 。 .
  • A 类 Gate 服务:字符串能力,批次(allowsMany),临时大门 (单位:千美元)define),角色,查询范围(scope +适配器' applyScope) (中文(简体) ).
  • 前端和工具: Inertia道具, 一个已键入 can() 从代码源、 客户端/ 反应 帮助者,测试帮助者,和一个允许 + 拒绝 望远镜的决定事件.

见 DESIGN.md 设计与权衡.

安装

pnpm add @nestjs/authorization @dudousxd/nestjs-authz

需要NestJS 12和节点24+. 两个可选的同伴: @nestjs/authentication 给 Gate 其环境用户( e)AuthenticationContext.user(三); @dudousxd/nestjs-context 给它一个也 (在认证范围之外),加上每个请求权限缓存和 租户范围的角色.

@Module({
  imports: [
    AuthorizationModule.forRoot(),                        // official: guard, @Can, AuthorizationService
    AuthzModule.forRoot({ superAdmin: (user) => user?.isRoot === true }),
  ],
  providers: [PostPolicy],
})
export class AppModule {}

政策(官方)+ @PolicyFor

import { Can, Policy } from '@nestjs/authorization';
import { AuthzPolicy, PolicyFor, authorizedResource, byId } from '@dudousxd/nestjs-authz';

@Policy()
@PolicyFor(Post)                       // optional: links Post → PostPolicy for the extras
export class PostPolicy extends AuthzPolicy {   // optional: honors `superAdmin`
  update(user: User | null, post: Post) {
    return post.authorId === user?.id;
  }
}

@Controller('posts')
export class PostController {
  @Patch(':id')
  @Can(PostPolicy, 'update', byId(Post))   // byId loads the Post named by :id
  update(@Req() req: Request) {
    const post = authorizedResource(req, Post); // the record byId loaded, no second query
  }
}

byId 使用该 ResourceResolver 授予 AuthzModule.forRoot({ resourceResolver }) (默认:a) { id } 来自路由参数的对象; idParam 重命名为它, byId(Post, { param }) 每条路线). 政策运行前的403个记录是找不到的.

@PolicyFor(Post) 让额外人员从资源到政策: gate.allows('update', post), (中文(简体) ), gate.scope(Post),客户端能力映射. 官方API( API) 从不需要它 @PolicyFor 应用官员 @Policy() 自己来.

角色和权限

@Roles('admin', 'editor')                                  // any of
@Can(RolePolicy, 'hasAll', roles('admin', 'editor'))      // all of
@Permission('posts.publish')                              // any of; posts.* grants it
@Can(PermissionPolicy, 'hasAll', permission('posts.publish', 'posts.delete'))

角色来自 user.roles 编号 : user.role (或 resolveRoles)和来自非洲区域局适配器的作用 存储; 适配器的权限 :

AuthzRbacModule.forRootAsync({
  inject: [DataSource],
  useFactory: (ds: DataSource) => ({ store: new TypeOrmAuthzStore(ds) }),
});

在一个请求内(一个巢js-context store),用户的权限和适配器的作用是 一次,不管多少次检查 官方警卫的 RolePolicy 编号 : PermissionPolicy 和处理者 Gate 呼叫共享获取。 该条目由用户名行键入 (类别或 type附加时 id; 普通对象没有 type 以身份键入。 补助金 从下一次请求中适用中期请求。 适应器集 exhaustivePermissions,所以一个 允许在不进行其他查询的情况下解答缺少的集.

roles(), (中文(简体) ), permission(), (中文(简体) ), ability() 财务报告和审定财务报表 staticCanArgs() 参数的返回解析器 不取决于电话。 {\fn华文楷体\fs20\bord1\shad1\1cHE0E0E0\2cH000000}被活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活活 Symbol.for('@dudousxd/static-can-args') 属性,因此Aviary代理等工具可以无需请求而评价某项要求.

超级管理员

官警只负责每个保单 before()扩展 AuthzPolicy (或打电话) superAdminBefore(user, ability, resource) 从你的 before())和 superAdmin 钩子 赋予这项政策的一切能力。 钩子接收资源( 能力的第一个) 因此它可以将绕行范围扩大. RolePolicy 财务报告和审定财务报表 PermissionPolicy 扩展它.

这个 Gate

constructor(private readonly gate: Gate) {}

await this.gate.forUser(user).authorize(PostPolicy, 'update', post); // = AuthorizationService.authorize
await this.gate.forUser(user).allows('update', post);                // the policy linked to Post
await this.gate.forUser(user).allows('posts.publish');               // a persisted permission

this.gate.define('access-admin', (user) => user.isStaff);
// on a route: @Can(GatePolicy, 'allows', ability('access-admin'))

const results = await this.gate.forUser(user).allowsMany([
  { ability: 'update', resource: post },
  { policy: ReportPolicy, ability: 'export', args: ['csv'] },
]);                                                                  // one permission fetch

const where = await this.gate.forUser(user).scope(Post);            // from PostPolicy.scope(user)

字符串能力询问 superAdmin,然后是外部决定点(以下),然后是政策 链接到资源,然后是持续的权限,然后是临时的门. 政策是 最后一个词: 持有其能力之一的许可(update没有 绕过; 只 superAdmin 已经 权限授予命名的能力没有定义策略 (单位:千美元)posts.publish) (中文(简体) ). 也一样 scope(): 仅当一个实体没有许可时, 才允许其范围 政策方法可以.

政策决定始终是公务部门的. authorize() 丢弃官方 AuthorizationError,正式模块变为401/403.

无 forUser,用户是:

  1. @nestjs/authentication是因为 AuthenticationContext.user,当该可选对等点是 已安装并导入其模块(通过 Nest 找到) ModuleRef),其范围是活跃的: 呼叫它处理,或 AuthenticationContext.run()答案是最后的: null 是一个 宾客,而"巢"字不问. 没错 AsyncLocalStorage- 支持,正确处理者 和他们所等待的;
  2. 不属于任何认证范围(排队工人、克龙工作或没有包), coryjs-context的用户参考文献,水分 resolveUser (按要求)配置时;
  3. 来宾(null) (中文(简体) ).

决定

每个 Gate 检查,并公布官方警卫执行的每一项要求,允许或 否认,在 aviary:authz:decision 诊断渠道(authzDecisionChannel) (中文(简体) ). 官员 软件包只发布拒绝, 在 nestjs:authorization:denied。 。 。 .

从0.8移走

0.8及更早时拥有自己的发动机. 0.9 运行 @nestjs/authorization和旧的 装饰器已去:将每个都移到正文.

0.8 (简体中文)0.9 (中文(简体) )
@Policy(Post)@Policy() 从 @nestjs/authorization + 键 @PolicyFor(Post) (或 @PolicyFor(Post) 页:1
@Can('update', Post)@Can(PostPolicy, 'update', byId(Post)), (中文(简体) ), @Can 从 @nestjs/authorization
@Can('create', Post, { classLevel: true })@Can(PostPolicy, 'create')
@Can('access-admin')@Can(GatePolicy, 'allows', ability('access-admin'))
@Roles('admin') + 键 RolesGuard@Roles('admin')由官方警卫执行
CanGuard, (中文(简体) ), RolesGuard, (中文(简体) ), PolicyRegistry删除: 官员 AuthorizationGuard· ; PolicyIndex
AuthzModule.forRoot({ policies })将政策登记为提供者(或 AuthorizationModule.forRoot({ policies })(中文(简体) )
superAdmin 在所有地方应用应用 AuthzPolicy 子类、内置政策和 Gate
after 钩子, { allowed, message } 结果删除: 仅一个字节 true 允许
当前用户在路由中的 courjs- context官员 getUser (默认) request.user(中文(简体) )
gate.allows() 来自 nockjs 文本的用户AuthenticationContext.user b. 其范围null 外面有客人,外有小鸟
以政策能力命名的持续许可政策决定(只有 superAdmin 绕过它,在检查和在 scope()
DecisionProvider 编号 : superAdmin 将客人视为 undefinednull
(单位:千美元) DecisionProvider 拒绝 message (单位:千美元){ allowed: false, message }403的讯息已删除: 403 是官方 { statusCode: 403, message: 'Forbidden' }。 。 。 . @nestjs/authorization 没有否认的理由(政策回报) true 或否认,或否认,或否认,或否认。 为了说明原因,自己扔 ForbiddenException(reason) 从能力。 一个路线,然后得到你的身体,但是没有 denied 事件被释放,并且 AuthorizationService.can() 抛出而不是返回 false。 。 。 .
DecisionProvider 每张支票都是门开的请求的 AuthzPolicy.before() 路线和途径 Gate 字符串能力
import … from '@dudousxd/nestjs-authz-inertia/client'import … from '@dudousxd/nestjs-authz-client' (子路径被移除)

官方警卫带来的行为:

  • 默认拒绝. 处理器没有 @Can() 拒绝; 添加 @Can.Anyone() (或 @Public() 从 @nestjs/authentication任何人都可以称之为它.
  • 类与方法要求相加. 一级 @Roles 不再让位于 方法学.
  • 来宾以 null。 。 。 . 输入用户 User | null;嘉宾否认为401.

一次移动一个控制器 : unannotated: 'allow'

官方的警卫否认任何路线 @Can():该应用的公用路线,和 每个控制器另装一个库。 0.8让他们通过。 开始授权 一个操作中的大型应用程序很少可能,所以这个软件包有迁移模式(官方守护) 没有这样的选择 :

  1. 关闭官方全球警戒,并切换迁移模式

    imports: [
      AuthenticationModule.forRoot({ ... }),                 // or your Passport guard, first
      AuthorizationModule.forRoot({ globalGuard: false }),
      AuthzModule.forRoot({ unannotated: 'allow' }),         // forRootAsync: next to useFactory
    ]
    

    AuthzModule 在全球注册 AuthzGuard。带有官方路线 @Can() 要求(类别或方法, @Roles, (中文(简体) ), @Permission) 已移交 致官员 AuthorizationGuard 同为: getUser同样的政策 同样的401个客人 和用户的403, 相同 denied 活动。 一个没有要求的路线被允许通过. 应用程序 如果官方全球卫士还在.

    启动日志在此模式中有一个预期错误 . @nestjs/authorization 检查 启动一个守卫执行每个 @Can(),它只承认自己的 AuthorizationGuard它没有看到 AuthzGuard因此,它记录:

    ERROR [Authorization] @Can() is not enforced on PostController.update, … : AuthorizationModule has
    globalGuard: false, and these handlers have no @UseGuards(AuthorizationGuard).
    

    这是安全的: AuthzGuard 执行这些操作员 AuthzModule 将行记录在后面 它命名他们。 错误在第四步消失.

  2. 放下0.8个后卫,移走老式装饰. 删除 RolesGuard 编号 : CanGuard 从 APP_GUARD 财务报告和审定财务报表 @UseGuards(),并重写每个字符串 @Can 编号 : @Policy(Post) 与表格 以上(单位:千美元)@Can('page.documents') → @Can(GatePolicy, 'allows', ability('page.documents'))) (中文(简体) ). @Roles('admin') 财务报告和审定财务报表 @Permission(...) 不变。 所有这一切都由 AuthzGuard。 。 。 .

  3. 注释开放路线,每次一个控制器 : @Can.Anyone() 任何人都可以打电话 这, @Public() (从) @nestjs/authentication在不需要签入的情况下,a @Can(...) 随所出处.

  4. 默认切换为拒绝 当每条路由声明某事时: 删除 unannotated (或设置) 'deny'和 globalGuard: false官方警卫又全球化了 被遗忘了 @Can() 是一个403而不是开放的路线.

第3步中滑入的路线在这个模式中是开放的,所以只保留为迁移.

外部政策引擎(Cerbos, OPA,.)

登记a DecisionProvider 下级 DECISION_PROVIDER 将决定交给外部政策 决策点。 与仅提供赠款的非洲区域局接头不同,它能够 允许或拒绝 资源意识检查. 正在返回 undefined 弃权者。 供应商也可以分批 gate.allowsMany,它可以绘制 引擎的查询计划进入 gate.scope()它运行在之后 superAdmin 钩:

  • 在路线上,在 before() 政策范围 AuthzPolicy,具有能力和 其第一个论点byId(Post)'记录'. RolePolicy 财务报告和审定财务报表 PermissionPolicy 不要问它: 他们的能力 指定角色和权限,而不是资源。 打电话 decisionProviderBefore() 从你自己 before() 当某项政策不能延长时 AuthzPolicy· ;
  • 输入 Gate,在策略,权限和一个字符串能力的特设门之前. allowsMany 询问 decideMany 一次为批次.

一个客人到达它作为 null箱内一个Cerbos适配器船作为无额外 依赖; 带来自己的 @cerbos/http 或者说 @cerbos/grpc 客户端 :

import { DECISION_PROVIDER } from '@dudousxd/nestjs-authz';
import { CerbosDecisionProvider } from '@dudousxd/nestjs-authz/cerbos';
import { HTTP } from '@cerbos/http';

providers: [{
  provide: DECISION_PROVIDER,
  useValue: new CerbosDecisionProvider({
    client: new HTTP(process.env.CERBOS_URL!),            // or (user) => per-tenant client | undefined
    principal: (u) => u && { id: u.id, roles: u.roles, attr: { tenantId: u.tenantId } },
    resource: (ability, r) => (r instanceof Post ? { kind: 'app:post', id: r.id, attr: { ownerId: r.ownerId } } : undefined),
    scope: { resource: (entity) => (entity === Post ? { kind: 'app:post' } : undefined) },
  }),
}]

适配器失败 关闭 默认。 无法获取的 PDP 否认和不支持的查询计划 瞄准到无行。 设定 onFailure: 'abstain' 转而回到自己的政策.

许可证

麻省理工学院

版本与发布记录

@dudousxd/nestjs-authz 共发布 21 个版本,首次发布于 2026/06/17;过去 12 个月发布了 21 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.11.0latest2026/11/121 天前
0.10.02026/11/121 天前
0.9.22026/11/094 天前
0.9.12026/11/085 天前
0.9.02026/11/085 天前
0.8.12026/10/2717 天前

关于 @dudousxd/nestjs-authz 的常见问题

@dudousxd/nestjs-authz 是什么?

在@nestjs/授权之上的外加:坚持RBAC的政策,@Can 帮助者(byId,角色,权限),一个带有批量检查和特设门的门,超级管理员,查询范围界定.

如何安装 @dudousxd/nestjs-authz?

在项目目录运行 npm install @dudousxd/nestjs-authz,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:rxjs(^7.1.0)、@nestjs/core(^12.0.0)、@nestjs/common(^12.0.0)、reflect-metadata(>=0.1.13)、@nestjs/authorization(^0.1.3)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@dudousxd/nestjs-authz 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@dudousxd/nestjs-authz 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@dudousxd/nestjs-authz 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=24。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@dudousxd/nestjs-authz 可以商用吗?

@dudousxd/nestjs-authz 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@dudousxd/nestjs-authz 的下载量有多少?

根据 npm 官方下载统计,@dudousxd/nestjs-authz 在 2026/10/13 – 2026/11/11 这 30 天内被下载 2,562 次,日均约 85 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@dudousxd/nestjs-authz 还在维护吗?

最新版本 0.11.0 发布于 2026/11/12(1 天前);至今共发布 21 个版本,其中过去 12 个月发布了 21 个;首次发布于 2026/06/17。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。