# @dudousxd/nestjs-authz 中文文档

规范地址：https://npmcn.com/package/%40dudousxd/nestjs-authz/

版本：0\.11\.0
npm 元数据更新时间：2026-11-12T10:42:08.792Z
中文译文更新时间：2026-11-13T01:48:51.052Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40dudousxd/nestjs-authz
原文对照：https://npmcn.com/package/%40dudousxd/nestjs-authz/?lang=original
项目主页：https://davidecarvalho.github.io/aviary/docs/authz
源码仓库：https://github.com/DavideCarvalho/nestjs-authz

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：418 kB，149 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=24
- 运行依赖：1 个
- 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，@nestjs/authentication ^0\.1\.5，@dudousxd/nestjs-context \>=0\.1\.0
- 首次发布：2026-06-17T12:41:24.173Z
- 最新版本发布：2026-11-12T10:42:08.396Z
- 近 30 天下载量：2562（2026-10-13 至 2026-11-11，npm 官方下载统计）
- 已发布版本数：21（近 12 个月 21 个）

## 中文简介

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

## 安装

```sh
npm install @dudousxd/nestjs-authz
```

也可以使用：`pnpm add @dudousxd/nestjs-authz`、`yarn add @dudousxd/nestjs-authz`、`bun add @dudousxd/nestjs-authz`

## README

[![@dudousxd/nestjs-authz — an Aviary library. Call sign: Falcon.](https://raw.githubusercontent.com/DavideCarvalho/nestjs-authz/main/.github/banner.svg)](https://davidecarvalho.github.io/aviary/docs/authz)

**[📖 读取文档](https://davidecarvalho.github.io/aviary/docs/authz)**  · 部分 [**飞行员**](https://davidecarvalho.github.io/aviary/) 雀巢生态系统

* * *

# `@dudousxd/nestjs-authz`

在NestJS的第一党之上的外加 [`@nestjs/authorization`](https://docs.nestjs.com/security/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`](https://github.com/DavideCarvalho/nestjs-authz/blob/main/DESIGN.md) 设计与权衡.

## 安装

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

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

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

## 政策(官方)+ `@PolicyFor`

```ts
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()` 自己来.

## 角色和权限

```ts
@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`)和来自非洲区域局适配器的作用 存储; 适配器的权限 :

```ts
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`

```ts
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` 将客人视为 `undefined` | `null` |
| (单位:千美元) `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.  **关闭官方全球警戒**,并切换迁移模式
    
    ```ts
    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`因此,它记录:
    
    ```text
    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` 客户端 :

```ts
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 是什么？

在@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 和提交记录判断。

