系统设计 / 访问控制 · 从 RBAC 查表到 policy 判定函数 / 可见性:内容「能不能看见」也是这个函数 待审核 22 / 23
实例 · 可见性 / 能不能看见

可见性:内容「能不能看见」也是这个函数

朋友圈「仅三天可见」、公众号测试文「只有指定人能看」、视频「你所在地区不可观看」、课程「开通 VIP 解锁」、ChatGPT「今日免费次数已用完」……这些看似五花八门的限制,是同一个函数:一次「把这条内容渲染给这个访客看吗」的判定,输入还是 授权请求 的那个四元组——who(访客身份与关系)、when/where(情境:地区 / 客户端 / 距发布多久)、what(内容自身:审核状态与作者设定的可见范围)、action(看见 / 可回复)。

图 0-1 · 可见性场景里的四个轴各自对应什么。

注 · 可见性是一串闸门(guard)的 AND:内容默认想展示,但要穿过若干道闸门——审核、登录、好友、地区、VIP、次数……每一道都放行才可见,任意一道拦下就受限。这正是 deny-overrides 的特例(全是 deny 类规则、必须全过)。与准入型授权不同的是:被拦下时不只返回「无权」,而是每道闸门都带一个 CTA(登录 / 开通 VIP / 下载 App / 关注作者…)——这就是 deny 携带的补救建议(advice),和 permit 携带的 obligation 正好对称。

1 · 可见性闸门链

以「微信朋友圈动态」预设为例,它启用「仅好友」与「最近三天可见」两道闸门。访客是陌生人时第一道就拦下;把关系切到好友,这道过了,但把距发布拉到 5 天前,时间这道又拦下——两道都满足才放行。

图 1-1 · 十二道可见性闸门对一次访问的逐道判定。可选内容预设或单独开关闸门,并调访客身份、关系与情境,观察内容在可见与受限之间翻转以及弹出的 CTA。

警示 ·「全部通过才可见」就是 AND,也就是 deny-overrides:任意一道不过,整条内容就不可见。设计时容易只盯着「我加的这道闸门」,而忘记它要和其他闸门共同成立——排查「为什么这个用户看不到」时,必须逐道核对,而不是只看最近改的那一条。

注 · UI 只展示「第一道没过的闸门」,这是 first-applicable。同时有多道没过时,真实产品不会把「登录 / 开通 VIP / 下载 App」全部同时弹出,而是按优先级挑最该先解决的那一道展示其 CTA。闸门的排列顺序(审核 → 登录 → 客户端 → 地区 → 关系 → 时间 → 付费 → 级别…)就决定了先逼用户过哪一关。

2 · 每种限制读的是哪个轴

它们之所以看着不一样而底子相同,是因为只是读了四元组里不同的字段。

表 2-1 · 十二种可见性限制各自读取的轴、现实例子与对应的 policy 概念。换字段就是换限制。
可见性限制 读哪个轴 / 字段 现实例子 policy 概念
审查 what.status 内容审核中 / 已下架时谁都看不到 读资源属性的 deny 规则
App 限制 where.client 活动分享页必须在 App 内打开才有功能 环境 / 客户端条件
登录限制 who.loggedIn 未登录只给摘要 / 不给看 匿名 vs 已认证主体
时间限制 when 相对 what 朋友圈三天 / 半年可见;软件试用期 环境(时间)+ 资源属性
群体 / 好友 / 指定人 who ↔ what 关系 朋友圈分组;公众号测试期仅指定人可见 基于关系的规则 = ReBAC 种子
付费限制 who.plan VIP 才能看 / 用 主体属性规则 = ABAC
级别(sVIP)限制 who.plan + level VIP 达到一定等级才解锁 属性的阶梯比较(像密级)
关注限制 who ↔ what 关系 豆瓣:关注用户才可见 / 可回复 关系规则 + 区分 action(看 vs 回复)
地区限制 where.region 视频 / 音乐版权按地区授权 环境(地点)条件
次数限制 who 用量 + when ChatGPT 免费 N 次 / 天 带状态的条件(用量计数 + 每日重置)
消费额限制 who.spend 累计消费达额后解锁权益 主体累积属性的阈值规则
软件版本限制 where.appVersion 旧版本不给用新功能 / 强制升级 环境(客户端版本)条件

建议 · 别把可见性当成内容上一组零散开关。它就是一个 canSee(viewer, context, content, 'view') → 可见 | 受限 + 该走哪个 CTA 的函数——一串 deny 闸门做 AND,失败时按优先级给出补救建议。理解了这一个函数,上面十二种、以及以后遇到的第十三种,都是同一回事。

3 · 参考文献

  1. 本系列。决策与组合算法。可见性是全是 deny 的 deny-overrides;展示哪个 CTA 则是 first-applicable
  2. 本系列。ReBAC:权限是一条边。仅好友 / 关注 / 指定人,都是 who ↔ what 的关系判定,那一页给出 tuple 与沿边传递的完整模型。
  3. 本系列。feature flag:输出 variant 而非 permit/deny。同样是「who → 看到哪一版」,可见性是它退化成二元情形。