从 RBAC 到 OpenFGA:细粒度授权的架构、落地与取舍

Posted on Thu 05 March 2026 in Tech • 8 min read

Abstract 从 RBAC 到 OpenFGA:细粒度授权的架构、落地与取舍
Authors Walter Fan
Category tech note
Status v1.0
Updated 2026-03-05
License CC-BY-NC-ND 4.0

从 RBAC 到 OpenFGA:细粒度授权的架构、落地与取舍

写了二十多年代码,我越来越觉得:认证(Authentication)是一道门,授权(Authorization)是一栋楼里的每一把锁。门只需要装一道,但锁要一间一间配,漏一间就是安全事故。

RBAC(Role-Based Access Control)是这栋楼里最常见的锁——简单、标准、够用。但当你的楼从一栋变成一个园区,从固定住户变成随时来去的访客,RBAC 就开始吃力了。

这篇文章从 RBAC 的局限出发,聊聊 OpenFGA 这把"新锁"——它的架构设计、落地路径、以及商业公司在"用开源"还是"自己造"之间的取舍。


一、RBAC:老黄牛的能力边界

1.1 RBAC 的核心模型

RBAC 的思路很直白:用户 → 角色 → 权限

User ──── Role ──── Permission
                      │
                   Action × Resource

一个典型的 RBAC 表结构:

-- 用户-角色关联
CREATE TABLE user_roles (
    user_id    BIGINT NOT NULL,
    role_id    BIGINT NOT NULL,
    PRIMARY KEY (user_id, role_id)
);

-- 角色-权限关联
CREATE TABLE role_permissions (
    role_id       BIGINT NOT NULL,
    permission_id BIGINT NOT NULL,
    PRIMARY KEY (role_id, permission_id)
);

-- 权限定义
CREATE TABLE permissions (
    id       BIGINT PRIMARY KEY,
    action   VARCHAR(50),   -- read, write, delete
    resource VARCHAR(100)   -- document, order, user
);

RBAC 的优势很明显:

  • 概念简单:产品经理、运维、审计都能理解
  • 实现成熟:Spring Security、Django Permission、Casbin 都有现成支持
  • 审计友好:谁有什么角色、角色有什么权限,一目了然
  • NIST 标准:RBAC 有 NIST INCITS 359-2004 标准,合规友好

1.2 RBAC 的三个痛点

但当系统复杂到一定程度,RBAC 的三个痛点就会暴露:

痛点一:角色爆炸(Role Explosion)

假设你有一个文档管理系统,需要控制:

  • 3 个部门(工程、产品、市场)
  • 4 种操作(查看、编辑、评论、删除)
  • 2 个数据范围(本部门、全公司)

纯 RBAC 需要 3 × 4 × 2 = 24 个角色。再加上项目维度、层级维度,角色数量指数增长。我见过一个企业系统有 800+ 个角色,没人说得清每个角色到底能干什么。

痛点二:无法表达资源间的关系

RBAC 回答的是"Alice 有 editor 角色",但回答不了"Alice 是 这个文件夹 的 editor,所以她也能编辑 文件夹里的文档"。

这种层级继承(Hierarchical Inheritance)在 Google Drive、GitHub、Notion 等产品中无处不在,但 RBAC 天然不支持。你要么在业务代码里硬编码继承逻辑,要么给每个资源单独分配角色——两种方案都很痛苦。

痛点三:动态共享难以建模

"Alice 把文档分享给 Bob,Bob 可以查看但不能编辑"——这是一个 实例级别 的权限,不是角色能覆盖的。RBAC 要实现这个,通常需要引入 ACL(Access Control List),但 ACL 和 RBAC 混用会让系统变得很难维护。

RBAC 能回答的问题:
  ✅ Alice 是管理员吗?
  ✅ 管理员能删除用户吗?

RBAC 回答不了的问题:
  ❌ Alice 能编辑 **这个** 文档吗?(实例级)
  ❌ Alice 是这个文件夹的 editor,她能编辑文件夹里的文档吗?(继承)
  ❌ Bob 被 Alice 分享了这个文档,他能查看吗?(动态共享)

二、Google Zanzibar:巨人的答案

2019 年,Google 发表了 Zanzibar 论文,揭示了 Google Drive、YouTube、Google Cloud 等产品背后的统一授权系统。

Zanzibar 的核心思想只有一个:一切权限都是关系(Relationship)

传统 RBAC:
  User → Role → Permission → Resource

Zanzibar / ReBAC:
  Subject ──relation──▶ Object
  (谁)     (什么关系)    (什么东西)

一条关系元组(Relationship Tuple)长这样:

document:readme#editor@user:alice

翻译成人话:Alice 是 readme 文档的 editor

这种模型的威力在于:关系可以 组合和继承

# Alice 是 engineering 文件夹的 editor
folder:engineering#editor@user:alice

# readme 文档在 engineering 文件夹里
document:readme#parent@folder:engineering

# 授权模型定义:文档的 editor 包括其父文件夹的 editor
type document
  relations
    define parent: [folder]
    define editor: [user] or editor from parent

现在问"Alice 能编辑 readme 吗?",Zanzibar 会沿着关系图遍历:

Alice ──editor──▶ folder:engineering
                        │
                     parent of
                        │
                        ▼
                  document:readme

结论:Alice 是 readme 的 editor ✅

这就是 ReBAC(Relationship-Based Access Control) 的核心——权限不是静态分配的,而是通过关系图动态推导的。


三、OpenFGA 架构深度剖析

OpenFGA 是 Auth0/Okta 开源的 Zanzibar 实现,现为 CNCF Sandbox 项目。已被 Grafana Labs、Canonical(Ubuntu)、Docker、Agicap、Read.AI 等公司采用。

3.1 整体架构

┌─────────────────────────────────────────────────────────┐
│                      应用层                              │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐              │
│  │ Service A │  │ Service B │  │ Service C │              │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘              │
│       │              │              │                    │
│       ▼              ▼              ▼                    │
│  ┌──────────────────────────────────────────┐           │
│  │           OpenFGA SDK (gRPC/HTTP)         │           │
│  └────────────────────┬─────────────────────┘           │
└───────────────────────┼─────────────────────────────────┘
                        │
                        ▼
┌───────────────────────────────────────────────────────────┐
│                   OpenFGA Server                          │
│                                                           │
│  ┌─────────────┐  ┌──────────────┐  ┌─────────────────┐ │
│  │ API Layer    │  │ Query Engine │  │ Change Tracker   │ │
│  │ (HTTP/gRPC)  │  │ (图遍历)     │  │ (变更日志)       │ │
│  └──────┬──────┘  └──────┬───────┘  └────────┬────────┘ │
│         │                │                    │          │
│         ▼                ▼                    ▼          │
│  ┌──────────────────────────────────────────────────┐   │
│  │              Storage Adapter                      │   │
│  │   PostgreSQL │ MySQL │ SQLite(beta) │ In-Memory   │   │
│  └──────────────────────────────────────────────────┘   │
└───────────────────────────────────────────────────────────┘

3.2 核心概念

概念 说明 示例
Store 隔离的授权数据空间,类似数据库 每个租户一个 Store
Authorization Model 定义类型、关系和权限推导规则 DSL 文件
Type 实体类型 user, document, folder
Relation 类型之间的命名关系 editor, viewer, parent
Tuple 具体的关系实例 document:readme#editor@user:alice
Condition 基于上下文的条件约束(ABAC 能力) ipAddress in allowedRange

3.3 核心 API

OpenFGA 只有 6 个核心 API,设计极其克制:

┌─────────────────────────────────────────────────────┐
│                    OpenFGA API                       │
├─────────────────────────────────────────────────────┤
│                                                     │
│  写入类:                                            │
│    Write()        - 写入/删除关系元组                  │
│    WriteModel()   - 更新授权模型                      │
│                                                     │
│  查询类:                                            │
│    Check()        - 检查某用户是否有某权限 → bool      │
│    ListObjects()  - 列出用户有权访问的所有对象          │
│    ListUsers()    - 列出对某对象有权限的所有用户        │
│    Expand()       - 展开权限的推导路径(调试用)        │
│                                                     │
│  管理类:                                            │
│    CreateStore()  - 创建 Store                       │
│    ReadChanges()  - 读取变更日志(审计/同步)          │
│                                                     │
└─────────────────────────────────────────────────────┘

其中最关键的是 Check() — 它是所有授权决策的入口:

from openfga_sdk import OpenFgaClient, ClientConfiguration
from openfga_sdk.client.models import ClientCheckRequest

config = ClientConfiguration(
    api_url="http://localhost:8080",
    store_id="your-store-id",
    authorization_model_id="your-model-id"
)

async with OpenFgaClient(config) as client:
    response = await client.check(ClientCheckRequest(
        user="user:alice",
        relation="editor",
        object="document:readme"
    ))
    print(response.allowed)  # True or False

3.4 授权模型 DSL

OpenFGA 的 DSL 是其最精妙的设计。一个 Google Drive 风格的模型:

model
  schema 1.1

type user

type organization
  relations
    define admin: [user]
    define member: [user] or admin

type folder
  relations
    define org: [organization]
    define owner: [user]
    define editor: [user] or owner or admin from org
    define viewer: [user] or editor or member from org

type document
  relations
    define parent: [folder]
    define owner: [user]
    define editor: [user] or owner or editor from parent
    define viewer: [user] or editor or viewer from parent
    define can_share: owner
    define blocked: [user]
    define can_view: viewer but not blocked
    define can_edit: editor but not blocked

这个模型表达了:

  1. 组织层级:admin 自动是 member
  2. 文件夹权限:org 的 admin 自动是文件夹的 editor
  3. 文档继承:文档继承父文件夹的权限
  4. 显式拒绝:被 blocked 的用户即使有其他权限也无法访问
  5. 分享控制:只有 owner 能分享文档

3.5 图遍历引擎

Check() 的核心是一个 有向图遍历 算法。当你问"Alice 能编辑 document:readme 吗?",引擎会:

1. 查找 document:readme 的 editor 关系定义
   → editor: [user] or owner or editor from parent

2. 分支搜索:
   ├── 直接关系:有没有 document:readme#editor@user:alice 元组?
   ├── owner 关系:Alice 是 readme 的 owner 吗?
   └── 继承关系:readme 的 parent folder 的 editor 包含 Alice 吗?
       ├── 查找 document:readme#parent@folder:* 元组
       │   → 找到 folder:engineering
       └── 递归检查 folder:engineering#editor@user:alice
           ├── 直接关系?
           ├── owner 关系?
           └── org admin 关系?
               → 继续遍历...

3. 任一分支返回 true → 最终结果 true

这个遍历有几个关键优化:

  • 并发遍历:多个分支并行检查,任一成功即短路返回
  • 缓存:热点元组和中间结果缓存
  • 深度限制:防止无限递归(默认最大深度 25)
  • 超时控制:单次 Check 有超时限制

四、RBAC vs ReBAC:不是替代,是演进

很多人问:用了 OpenFGA 是不是就不需要 RBAC 了?不是

┌──────────────────────────────────────────────────────────┐
│                    授权模型演进                            │
│                                                          │
│  ACL ──▶ RBAC ──▶ ABAC ──▶ ReBAC                        │
│  (列表)   (角色)   (属性)   (关系)                         │
│                                                          │
│  简单 ◀──────────────────────────────────────▶ 灵活       │
│  粗粒度 ◀────────────────────────────────────▶ 细粒度     │
└──────────────────────────────────────────────────────────┘
维度 RBAC ReBAC (OpenFGA)
核心抽象 角色 关系
粒度 资源类型级 资源实例级
继承 角色继承(有限) 关系图遍历(灵活)
动态共享 需要额外 ACL 原生支持
性能 O(1) 查表 O(n) 图遍历
复杂度 中高
适用场景 后台管理、API 网关 文档协作、多租户 SaaS
学习曲线

我的建议:大多数系统应该 RBAC + ReBAC 混合使用

  • 粗粒度(API 级别):用 RBAC。"只有 admin 能访问 /admin/* 接口"——简单直接。
  • 细粒度(资源级别):用 ReBAC。"Alice 能编辑这个文档吗?"——需要关系推导。
# 两层授权的伪代码
@app.route("/api/documents/<doc_id>", methods=["PUT"])
@require_role("editor")  # 第一层:RBAC,粗粒度
async def update_document(doc_id):
    # 第二层:ReBAC,细粒度
    allowed = await fga_client.check(
        user=f"user:{current_user.id}",
        relation="editor",
        object=f"document:{doc_id}"
    )
    if not allowed:
        return {"error": "Forbidden"}, 403
    # ... 业务逻辑

五、商业公司落地路径

5.1 渐进式迁移策略

不要试图一步到位。我建议分四个阶段:

Phase 1          Phase 2          Phase 3          Phase 4
评估与 PoC        影子模式          逐步切换          全面迁移
(2-4 周)         (4-8 周)         (8-16 周)        (持续)
   │                │                │                │
   ▼                ▼                ▼                ▼
┌────────┐    ┌────────────┐   ┌────────────┐   ┌──────────┐
│建模     │    │双写双读     │   │新功能用 FGA │   │旧功能迁移 │
│原型验证  │    │对比结果     │   │旧功能保持   │   │下线旧系统 │
│性能测试  │    │不影响线上   │   │逐步切换     │   │          │
└────────┘    └────────────┘   └────────────┘   └──────────┘

Phase 1:评估与 PoC(2-4 周)

  • 梳理现有权限模型,识别 RBAC 覆盖不了的场景
  • 用 OpenFGA Playground 建模,验证能否表达业务需求
  • 做性能基准测试:Check() 延迟、Write() 吞吐量

Phase 2:影子模式(4-8 周)

这是最关键的一步。在不影响线上的前提下验证正确性:

async def check_permission(user, action, resource):
    # 旧系统做决策(线上生效)
    old_result = rbac_check(user, action, resource)

    # 新系统做决策(仅记录,不生效)
    new_result = await fga_check(user, action, resource)

    # 对比结果
    if old_result != new_result:
        logger.warning(f"Authorization mismatch: "
                      f"user={user}, action={action}, resource={resource}, "
                      f"old={old_result}, new={new_result}")
        metrics.increment("authz.mismatch")

    return old_result  # 仍然用旧系统的结果

Phase 3:逐步切换(8-16 周)

  • 新功能直接用 OpenFGA
  • 旧功能按模块逐步切换,每次切换一个模块
  • 保留回滚开关(Feature Flag)

Phase 4:全面迁移(持续)

  • 下线旧的 RBAC 表和代码
  • 建立授权模型的 CI/CD 流程
  • 完善监控和告警

5.2 数据同步:最容易踩的坑

OpenFGA 的关系元组需要和业务数据保持一致。这是落地中 最容易出问题 的地方。

业务事件                    OpenFGA 操作
─────────                  ──────────────
用户加入团队     ──────▶    Write(team:X#member@user:alice)
用户离开团队     ──────▶    Delete(team:X#member@user:alice)
文档移动到新文件夹 ──────▶   Delete(doc:Y#parent@folder:old)
                           Write(doc:Y#parent@folder:new)
文档被删除       ──────▶    Delete(doc:Y 相关的所有元组)

三种同步方案

方案 一致性 复杂度 适用场景
同步写入(业务操作和 FGA 写入在同一事务) 强一致 高(分布式事务) 金融、医疗
事件驱动(业务写 DB → 发事件 → Consumer 写 FGA) 最终一致 大多数场景
定时全量同步(定期从业务 DB 全量导入 FGA) 弱一致 PoC、非关键场景

我推荐大多数公司用 事件驱动 方案,配合幂等写入和补偿机制:

# Kafka Consumer 示例
async def handle_team_member_event(event):
    if event.type == "MEMBER_ADDED":
        await fga_client.write(writes=[
            ClientTupleKey(
                user=f"user:{event.user_id}",
                relation="member",
                object=f"team:{event.team_id}"
            )
        ])
    elif event.type == "MEMBER_REMOVED":
        await fga_client.write(deletes=[
            ClientTupleKeyWithoutCondition(
                user=f"user:{event.user_id}",
                relation="member",
                object=f"team:{event.team_id}"
            )
        ])

5.3 性能考量

OpenFGA 的 Check() 延迟取决于关系图的深度和宽度。根据官方基准和社区反馈:

场景 典型延迟 说明
直接关系 < 5ms document:X#editor@user:alice 直接匹配
一层继承 5-15ms 需要查一次 parent
多层继承 15-50ms 3-4 层嵌套
复杂模型 50-200ms 多个 union/intersection/exclusion

优化手段

  1. 控制模型深度:继承层级不超过 3-4 层
  2. 合理使用 ListObjects:批量查询比逐个 Check 高效
  3. 客户端缓存:对变化不频繁的权限做短时缓存(TTL 30-60s)
  4. 水平扩展:OpenFGA Server 无状态,可以水平扩展
  5. 数据库优化:PostgreSQL 配合连接池和索引优化

六、风险分析

6.1 技术风险

风险 影响 缓解措施
OpenFGA 服务不可用 所有授权决策失败 多副本部署 + 客户端缓存 + 降级策略(fail-open 或 fail-close)
数据不一致 权限判断错误 事件驱动 + 补偿任务 + 定期全量校验
模型变更导致权限变化 意外的权限放大或收缩 模型版本管理 + 影子模式验证 + 回滚机制
性能退化 接口延迟增加 监控 P99 延迟 + 告警 + 缓存 + 限制模型复杂度
关系元组膨胀 存储和查询压力 定期清理孤儿元组 + 监控元组数量

6.2 组织风险

  • 学习曲线:ReBAC 的思维方式和 RBAC 不同,团队需要时间适应。建议先做内部培训和 Workshop。
  • 运维负担:多了一个有状态服务(OpenFGA + PostgreSQL),需要 DBA 和 SRE 支持。
  • 供应商锁定:虽然 OpenFGA 是开源的,但如果深度集成后迁移成本很高。
  • 社区成熟度:OpenFGA 是 CNCF Sandbox 项目(非 Graduated),社区规模和生态还在成长中。

6.3 降级策略

授权服务是关键路径,必须有降级方案:

async def check_with_fallback(user, relation, obj):
    try:
        result = await asyncio.wait_for(
            fga_client.check(user=user, relation=relation, object=obj),
            timeout=0.5  # 500ms 超时
        )
        return result.allowed
    except (TimeoutError, ConnectionError) as e:
        logger.error(f"OpenFGA unavailable: {e}")
        metrics.increment("authz.fallback")

        # 降级策略选择:
        # 方案 A: fail-close(安全优先,拒绝所有请求)
        # return False

        # 方案 B: fail-open(可用性优先,允许所有请求)
        # return True

        # 方案 C: 回退到本地缓存或旧 RBAC 系统(推荐)
        return local_cache.get(f"{user}:{relation}:{obj}", False)

七、开源 vs 自研:取舍之道

这是每个技术团队都会面临的问题。我把市面上的选择梳理一下:

7.1 开源方案对比

项目 背景 模型 语言 存储 成熟度 商业支持
OpenFGA Auth0/Okta Zanzibar Go PG/MySQL/SQLite CNCF Sandbox Okta FGA (SaaS)
SpiceDB Authzed Zanzibar Go PG/CockroachDB/Spanner 生产就绪 Authzed (SaaS)
Ory Keto Ory Zanzibar Go PG/MySQL Beta Ory Network (SaaS)
Casbin 社区 RBAC/ABAC/ACL Go/多语言 多种 成熟
OPA CNCF 通用策略 Go 无(内存) Graduated Styra (SaaS)

OpenFGA vs SpiceDB 是最常被比较的两个:

  • OpenFGA:Okta 背书,SDK 丰富(Java/Go/Python/Node/.NET),Playground 好用,社区活跃度高。适合已经在用 Auth0/Okta 生态的团队。
  • SpiceDB:API 设计更贴近 Zanzibar 原论文,支持 CockroachDB 和 Spanner(全球分布式),Watch API 更成熟。适合需要全球部署的大规模系统。

7.2 自研的诱惑与代价

我见过不少团队选择自研授权系统,理由通常是:

  • "我们的业务模型很特殊,开源方案不够灵活"
  • "不想引入外部依赖,增加运维复杂度"
  • "我们有能力自己做,而且可以完全掌控"

这些理由都有道理,但自研的代价往往被低估:

自研授权系统的隐性成本:

┌─────────────────────────────────────────────────┐
│  显性成本(大家都能看到的)                        │
│  ├── 开发:3-6 个月,2-3 个高级工程师              │
│  └── 测试:权限组合爆炸,测试用例指数增长           │
│                                                   │
│  隐性成本(容易被忽略的)                          │
│  ├── 性能优化:图遍历算法、缓存策略、并发控制       │
│  ├── 一致性保证:分布式环境下的数据同步             │
│  ├── 模型演进:业务变化时的 schema migration       │
│  ├── 安全审计:权限变更的审计日志和合规报告         │
│  ├── 运维监控:延迟、错误率、元组数量的监控告警     │
│  ├── 文档培训:新人上手成本                        │
│  └── 持续维护:Bug 修复、安全补丁、版本升级         │
│                                                   │
│  机会成本(最容易被忽略的)                        │
│  └── 这些工程师本可以做什么业务功能?               │
└─────────────────────────────────────────────────┘

7.3 我的决策框架

                    ┌──────────────────┐
                    │ 你的授权需求是?  │
                    └────────┬─────────┘
                             │
                    ┌────────▼─────────┐
                    │ 只需要角色级控制? │
                    └────────┬─────────┘
                        是 /     \ 否
                         /         \
              ┌─────────▼┐    ┌────▼──────────┐
              │ 用 RBAC   │    │ 需要资源级     │
              │ (框架自带) │    │ 细粒度控制?   │
              └──────────┘    └────┬──────────┘
                              是 /     \ 否
                               /         \
                    ┌─────────▼┐    ┌────▼──────────┐
                    │ 团队 > 50 │    │ 用 RBAC + ACL │
                    │ 人?有 SRE │    │ (Casbin/OPA)  │
                    │ 支持?     │    └───────────────┘
                    └─────┬────┘
                     是 /     \ 否
                      /         \
           ┌─────────▼┐    ┌────▼──────────┐
           │ 用 OpenFGA │    │ 用 OpenFGA    │
           │ 或 SpiceDB │    │ 但从小处开始  │
           │ 全面部署   │    │ 先 PoC 再扩展 │
           └───────────┘    └───────────────┘

什么时候该自研?

老实说,只有极少数情况:

  1. 超大规模:日均 Check 请求 > 10 亿次,需要深度定制存储和缓存层
  2. 强合规要求:金融/医疗行业,监管要求授权系统必须完全自主可控
  3. 已有成熟基础设施:团队已经有图数据库、分布式缓存等基础设施,且有专门的平台团队维护

除此之外,用开源方案 + 适度定制 几乎总是更好的选择。


八、实战建议

8.1 授权模型设计原则

  1. 从业务场景出发,而非从技术出发。先画出"谁能对什么做什么"的关系图,再翻译成 DSL。
  2. 控制继承深度。超过 4 层的继承会显著影响性能,也会让模型难以理解。
  3. 显式优于隐式。宁可多写几行 DSL,也不要依赖隐含的权限推导。
  4. 测试先行。OpenFGA CLI 支持模型测试,把测试用例写在模型旁边:
# model_test.yaml
- name: "folder editor can edit documents in folder"
  tuples:
    - user: "user:alice"
      relation: "editor"
      object: "folder:engineering"
    - user: "folder:engineering"
      relation: "parent"
      object: "document:readme"
  checks:
    - user: "user:alice"
      relation: "editor"
      object: "document:readme"
      assertion: true
    - user: "user:bob"
      relation: "editor"
      object: "document:readme"
      assertion: false

8.2 监控指标

上线后必须监控的指标:

授权系统健康度仪表盘:

┌─────────────────────────────────────────────┐
│  Check() P50 延迟    │  Check() P99 延迟     │
│  ████████ 3ms        │  ████████████ 45ms    │
├──────────────────────┼──────────────────────┤
│  Check() 错误率      │  Write() 吞吐量       │
│  ██ 0.01%            │  ████████ 1.2K/s      │
├──────────────────────┼──────────────────────┤
│  关系元组总数         │  降级触发次数          │
│  ████████ 2.3M       │  █ 0                  │
└──────────────────────┴──────────────────────┘

8.3 常见陷阱

  1. 不要把 OpenFGA 当数据库用。它是授权引擎,不是通用存储。不要把业务数据塞进元组。
  2. 不要忽略元组清理。用户离职、资源删除后,相关元组要及时清理,否则会有"幽灵权限"。
  3. 不要在热路径上做 ListObjects。ListObjects 比 Check 慢得多,适合用在"展示用户能看到的资源列表"场景,不适合用在每次请求的权限校验中。
  4. 不要跳过影子模式。直接切换到新系统,出了问题就是线上事故。影子模式是你的安全网。

九、总结

维度 建议
模型选择 RBAC 做粗粒度(API 级),ReBAC 做细粒度(资源级),混合使用
方案选择 优先 OpenFGA/SpiceDB 等开源方案,除非有超大规模或强合规需求才考虑自研
落地路径 PoC → 影子模式 → 逐步切换 → 全面迁移,不要一步到位
数据同步 事件驱动 + 幂等写入 + 定期校验
风险控制 降级策略 + 监控告警 + 模型版本管理 + 回滚机制

授权系统是那种"做对了没人注意,做错了全公司都知道"的基础设施。选择合适的工具、渐进式落地、持续监控——这三件事做好,就能让这栋楼里的每一把锁都锁得住。

一句话总结:RBAC 是标准间的门卡,OpenFGA 是整栋楼的智能门禁——不是替代,是升级。从小处开始,用影子模式验证,让数据说话。


参考资料


思维导图

从 RBAC 到 OpenFGA 思维导图

@startmindmap
<style>
mindmapDiagram {
  node { BackgroundColor #FAFAFA }
  :depth(0) { BackgroundColor #FFD700 }
  :depth(1) { BackgroundColor #E3F2FD }
  :depth(2) { BackgroundColor #F5F5F5 }
}
</style>
title 从 RBAC 到 OpenFGA
* 授权体系
** RBAC
*** 用户→角色→权限
*** 优势:简单、标准、审计友好
*** 痛点
**** 角色爆炸
**** 无法表达资源关系
**** 动态共享难建模
** Zanzibar / ReBAC
*** 一切权限都是关系
*** Subject ─relation─▶ Object
*** 关系图遍历推导权限
** OpenFGA 架构
*** API Layer (HTTP/gRPC)
*** Query Engine (图遍历)
*** Storage (PG/MySQL/SQLite)
*** 6 个核心 API
**** Check / ListObjects / ListUsers
**** Write / WriteModel / Expand
** 落地路径
*** Phase 1: PoC (2-4周)
*** Phase 2: 影子模式 (4-8周)
*** Phase 3: 逐步切换 (8-16周)
*** Phase 4: 全面迁移
** 数据同步
*** 同步写入(强一致)
*** 事件驱动(最终一致,推荐)
*** 定时全量(弱一致)
** 风险控制
*** 服务不可用 → 降级策略
*** 数据不一致 → 补偿任务
*** 模型变更 → 版本管理
*** 性能退化 → 监控告警
** 开源 vs 自研
*** OpenFGA: Okta 背书, SDK 丰富
*** SpiceDB: 全球分布式
*** 自研:仅超大规模/强合规
*** 决策:用开源 + 适度定制
@endmindmap

本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。