第十七章:授权架构模式

“好的授权架构应该像空气一样:无处不在,但用户感觉不到它的存在。”

        mindmap
  root((授权架构))
    演进
      硬编码
      配置文件
      策略引擎
      外部化授权
    XACML 架构
      PEP
      PDP
      PIP
      PAP
    微服务模式
      Gateway
      Service Mesh
      应用层
      混合
    多租户
      租户隔离
      权限继承
      跨租户
    

17.1 授权架构的演进

Level 0: 硬编码
if user.role == "admin":
    allow()
→ 问题:修改权限需要改代码、重新部署

Level 1: 配置文件
permissions = load_config("permissions.yaml")
→ 问题:缺乏测试、审计,配置散落各处

Level 2: 策略引擎
result = opa.evaluate(input)
→ 改进:策略与代码分离,可测试

Level 3: 外部化授权(Authorization as a Service)
result = authz_service.check(user, action, resource)
→ 最佳:统一授权服务,所有应用共享

17.2 XACML 授权架构

┌──────────┐    ┌──────────┐    ┌──────────┐
│  用户     │───▶│   PEP    │───▶│  应用     │
│          │    │ 策略执行点 │    │ 资源      │
└──────────┘    └────┬─────┘    └──────────┘
                     │
                     │ 授权请求
                     ▼
                ┌──────────┐
                │   PDP    │◀──── ┌──────────┐
                │ 策略决策点 │      │   PAP    │
                │ (OPA/    │      │ 策略管理点 │
                │  OpenFGA)│      │ (管理界面) │
                └────┬─────┘      └──────────┘
                     │
                     │ 查询属性
                     ▼
                ┌──────────┐
                │   PIP    │
                │ 策略信息点 │
                │ (用户属性 │
                │  资源属性) │
                └──────────┘

组件

职责

实现

PEP

拦截请求,执行决策

API Gateway、中间件、Sidecar

PDP

评估策略,做出决策

OPA、OpenFGA、Cedar

PIP

提供决策所需的属性数据

用户服务、LDAP、数据库

PAP

管理策略的创建和更新

管理界面、Git

17.3 微服务授权模式

模式 1:Gateway 集中授权

┌──────────┐    ┌──────────────┐    ┌──────────┐
│  客户端   │───▶│  API Gateway  │───▶│  微服务   │
│          │    │  ┌─────────┐ │    │ 信任 GW  │
│          │    │  │ 认证    │ │    │ 不做授权  │
│          │    │  │ 授权 ✅ │ │    │          │
│          │    │  │ 限流    │ │    │          │
│          │    │  └─────────┘ │    │          │
└──────────┘    └──────────────┘    └──────────┘

优点:简单、集中管理 缺点:粗粒度、Gateway 成为瓶颈

模式 2:Service Mesh 授权

┌──────────────────────────────────────┐
│  Kubernetes Pod                       │
│  ┌──────────┐    ┌────────────────┐  │
│  │  微服务   │◀──▶│  Envoy Sidecar │  │
│  │ 业务逻辑  │    │  ┌──────────┐ │  │
│  │          │    │  │ mTLS     │ │  │
│  │          │    │  │ AuthzPolicy│ │  │
│  │          │    │  └──────────┘ │  │
│  └──────────┘    └────────────────┘  │
└──────────────────────────────────────┘

模式 3:应用层授权

# 应用内授权 — 最细粒度
@app.put("/api/documents/{doc_id}")
async def update_document(
    doc_id: str,
    user: User = Depends(get_current_user),
):
    # 调用外部授权服务
    allowed = await openfga_client.check(
        user=f"user:{user.id}",
        relation="can_edit",
        object=f"document:{doc_id}",
    )
    if not allowed:
        raise HTTPException(403, "Cannot edit this document")
    
    # 业务逻辑...

模式 4:混合模式(推荐)

┌──────────┐    ┌──────────────┐    ┌──────────────────┐
│  客户端   │───▶│  API Gateway  │───▶│  微服务            │
│          │    │  粗粒度授权   │    │  ┌──────────────┐ │
│          │    │  • 认证       │    │  │ 细粒度授权    │ │
│          │    │  • 角色检查   │    │  │ • 资源级权限  │ │
│          │    │  • 速率限制   │    │  │ • OpenFGA    │ │
│          │    │              │    │  │ • OPA        │ │
│          │    │              │    │  └──────────────┘ │
└──────────┘    └──────────────┘    └──────────────────┘

17.4 多租户授权设计

多租户授权模型(OpenFGA):

type user

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

type project
  relations
    define tenant: [tenant]
    define admin: [user] or admin from tenant
    define member: [user] or admin
    define can_manage: admin
    define can_access: member or can_manage

type resource
  relations
    define project: [project]
    define owner: [user]
    define editor: [user] or owner or can_manage from project
    define viewer: [user] or editor or can_access from project

租户隔离策略

策略

描述

实现

数据隔离

每个租户的数据完全隔离

数据库 schema/表前缀

权限隔离

租户 A 的用户无法访问租户 B

OpenFGA 关系检查

管理隔离

租户管理员只能管理自己的租户

租户级 admin 角色

跨租户访问

特殊场景下的跨租户协作

显式的跨租户关系元组

17.5 性能优化

缓存策略

import redis
import json
from functools import lru_cache

r = redis.Redis()

async def check_permission_cached(user_id: str, relation: str, object_id: str) -> bool:
    """带缓存的权限检查"""
    cache_key = f"authz:{user_id}:{relation}:{object_id}"
    
    # 1. 检查缓存
    cached = r.get(cache_key)
    if cached is not None:
        return cached == b"1"
    
    # 2. 调用 OpenFGA
    result = await openfga_client.check(
        user=f"user:{user_id}",
        relation=relation,
        object=object_id,
    )
    
    # 3. 写入缓存(TTL 60秒)
    r.setex(cache_key, 60, "1" if result.allowed else "0")
    
    return result.allowed

def invalidate_permission_cache(object_id: str):
    """权限变更时清除相关缓存"""
    pattern = f"authz:*:*:{object_id}"
    for key in r.scan_iter(pattern):
        r.delete(key)

批量检查

async def batch_check_permissions(user_id: str, objects: list[str], relation: str) -> dict:
    """批量权限检查"""
    results = {}
    checks = [
        openfga_client.check(
            user=f"user:{user_id}",
            relation=relation,
            object=obj,
        )
        for obj in objects
    ]
    responses = await asyncio.gather(*checks)
    for obj, resp in zip(objects, responses):
        results[obj] = resp.allowed
    return results

17.6 实战:SaaS 平台授权架构

┌─────────────────────────────────────────────────────┐
│                    SaaS 平台授权架构                  │
│                                                      │
│  ┌──────────┐    ┌──────────────┐    ┌───────────┐  │
│  │ Web/Mobile│───▶│ API Gateway  │───▶│ 微服务集群 │  │
│  │ 客户端    │    │ (Kong/Envoy) │    │           │  │
│  └──────────┘    │ • JWT 验证   │    │ ┌───────┐ │  │
│                  │ • 租户路由   │    │ │用户服务│ │  │
│                  │ • 速率限制   │    │ └───┬───┘ │  │
│                  └──────────────┘    │     │     │  │
│                                     │     ▼     │  │
│  ┌──────────────────────────────┐   │ ┌───────┐ │  │
│  │      授权服务层               │   │ │项目服务│ │  │
│  │  ┌──────────┐ ┌───────────┐ │   │ └───┬───┘ │  │
│  │  │ OpenFGA  │ │   OPA     │ │   │     │     │  │
│  │  │ (ReBAC)  │ │  (ABAC)   │ │   │     ▼     │  │
│  │  │ 关系权限  │ │  条件策略  │ │   │ ┌───────┐ │  │
│  │  └──────────┘ └───────────┘ │   │ │资源服务│ │  │
│  └──────────────────────────────┘   │ └───────┘ │  │
│                                     └───────────┘  │
└─────────────────────────────────────────────────────┘

17.7 小结

  • 授权架构从硬编码演进到外部化授权即服务

  • XACML 架构(PEP/PDP/PIP/PAP)是授权系统的标准参考架构

  • 混合模式最实用:Gateway 粗粒度 + 应用层细粒度

  • 多租户授权需要数据隔离、权限隔离、管理隔离

  • 缓存和批量检查是授权性能优化的关键手段

  • OpenFGA(ReBAC)+ OPA(ABAC)的组合覆盖大多数授权需求