2. 权限管理基础概念:主体、客体、操作、权限规则与策略

权限管理这东西,听起来玄乎,说白了就四个词:谁(主体)、对什么(客体)、做什么(操作)、怎么管(规则与策略)。我们在SDK里做隐私共享,其实就是在回答这四个问题。我记得刚入行时,总觉得只有操作系统内核才需要权限管理,后来被甲方追着改了好几版才明白——SDK里的权限比系统级还麻烦,因为你不光要管App,还得管App里的模块。

2.1 主体(Subject)

主体就是“谁”在发起请求。在隐私共享SDK里,主体可以是:

  • 第三方App进程(最常见的主洗)
  • App内的子模块或插件(比如一个广告组件)
  • 远程服务调用者(跨进程或跨设备)
  • 用户代理(经用户授权后的自动化程序)
我个人的一个习惯:如果你在SDK内部给主体贴标签,千万别只用PID或包名。我见过一个项目,进程PID会复用,结果权限张冠李戴。我推荐用“签名+包名+UID”的组合,或者给每个接入方分配一个。

2.2 客体(Object)

客体就是主体要访问的“东西”。在隐私共享场景里,客体一般是:

  • 用户数据项:通讯录、位置、相册、设备标识符
  • SDK内部资源:加密密钥、缓存池、日志流
  • 特定功能接口:比如“上报数据API”、“删除记录API”

这里有个坑:客体粒度太粗的话,后期根本没法单独管控。我曾经接了一个SDK,把“所有用户数据”当成了一个客体,结果想单独禁止某个App读取位置都不行。所以建议一开始就把客体拆细,比如“com.example.location.gps”和“com.example.contacts.phones”。

2.3 操作(Operation)

操作就是主体对客体“做什么”。常用的操作集:

  1. 读取(read):获取数据内容
  2. 写入(write):修改或新增数据
  3. 删除(delete):移除数据项
  4. 执行(execute):调用一个功能接口
  5. 共享(share):把数据传给第三方(比较特殊,我后面会讲)

避坑指南:我曾经把“读取”和“写入”权限用同一个位掩码来标记,结果某个App强行把写操作伪装成读操作。后来我强制规定:每个操作必须有独立的标识符,并且在SDK内部使用白名单校验。

2.4 权限规则与策略

有了主体、客体、操作,接下来就是“怎么判定”。权限规则是一条条具体的判断条件,而策略是规则的集合,包含优先级、合并方式、默认行为。

2.4.1 规则(Rule)

规则通常写成三元组:(主体, 客体, 操作) → 允许/拒绝。举个例子:

// 规则表示:包名为 com.example.reader 的App,允许读取通讯录
{
  "subject": "pkg:com.example.reader",
  "object": "data:contacts",
  "operation": "read",
  "effect": "allow"
}

你想想看,规则越具体越好。但要注意,规则太多会影响性能。我建议把规则缓存成HashMap,主体和客体都用整数ID代替字符串。

2.4.2 策略(Policy)

策略是一组规则的容器,外加一个冲突解决机制。比如:

策略属性取值示例说明
rules规则列表包含多条具体的 allow/deny 规则
defaultEffectdeny没有匹配时默认禁止(安全第一)
conflictResolutiondeny-overrides 或 allow-overrides当多条规则冲突时,拒绝优先还是允许优先
combineAlgfirst-match / prioritize / cascading规则组合方式

注意:策略的默认行为千万别设成“allow”,那等于所有App都可以随便取数据。我早期一个版本就是默认允许,结果灰度测试时被安全团队当场喊停。一定用“deny by default”!

讲完这些基本概念,为了方便你理解它们之间的关系,我画了一张结构图。你看一遍应该就能记住。

权限管理四要素关系图 主体(Subject) 客体(Object) 操作(Operation) 规则(Rule) (主体,客体,操作) → 允许/拒绝 策略(Policy) 规则集合 + 默认行为 + 冲突解决 策略是规则的上层容器

你看,主体、客体、操作三个兄弟一起喂给规则,规则再喂给策略,策略最终输出权限判定。顺序很清楚。

2.5 实战中的常见模型

咱们SDK里一般不会裸用三元组,而是封装成更高层的模型。我简单列两个:

  • ACL(访问控制列表):每个客体挂一个列表,列出哪些主体可以做什么。适合客体数量少、主体数量多的场景。我曾在接触者数据模块用过,因为数据项就那么几个,但接入方很多。
  • RBAC(基于角色的访问控制):主体不直接绑规则,而是通过角色间接获取权限。适合权限层次复杂的SDK。比如“付费用户”角色可以读更多数据。不过要注意角色继承不能死循环,我踩过这个坑。

我的建议:初期先用ACL,简单直观;等权限规则膨胀到上百条时再切换到RBAC。别一开始就上复杂的模型,不然你自己都搞不清楚谁有什么权限。

2.6 权限判定的核心步骤

你可以把整个判定过程想象成一个流水线:

  1. 提取主体身份(签名、包名、UID)
  2. 定位目标客体(根据请求的资源路径)
  3. 确认操作类型(read / write / execute等)
  4. 加载对应策略(按客体或按主体加载)
  5. 逐条匹配规则,直到命中第一条或达到默认结果
  6. 返回允许/拒绝,并记录审计日志

嗯,这里有个细节要注意:审计日志最好记录“拒绝”的触发规则。我曾经为了调试一个权限问题,翻了一天的日志才发现是某条规则写得太宽泛。

掌握好这四个基础概念,后面讲“授权模型”和“最小权限原则”的时候你就会觉得很轻松。它们就是整个课程的基石。