系统设计 / 访问控制 · 从 RBAC 查表到 policy 判定函数 / when[where]:同一请求,换个时间地点就从准变拒 待审核 14 / 23
when/where · 环境

when[where]:同一请求,换个时间地点就从准变拒

有一类条件,既不属于「人」也不属于「物」,而属于请求发生的现场——环境/情境(environment / context):当前时刻、星期几、来自哪个网络(公司 / 家里 / 境外)、使用何种设备(公司托管 / 个人)、是否已通过 MFA。

1 · 情境对决策的影响

两组对照最能说明问题。其一,场景「admin 导出预算」:office + 托管设备是准;切到境外则 r-abroad 一票否决,切到个人设备且关闭 MFA 则 r-mfa 拦截。其二,场景「approver 审批」:工作日 10:00 是准;拖到 22:00 或切到周日,不在工作时间,r-approve 不再命中,无人放行,落到默认拒绝。

图 1-1 · who / what / action 全部固定时,情境变化引起的决策翻转。可调时刻、星期、网络、设备与 MFA 状态,观察规则命中与最终决策。

注 · 同一个人、同一个动作、同一份资源,仅因情境不同便给出相反结论——这是 RBAC 的静态「role → permission 表」天然表达不了的。把 context 纳入函数参数,授权才谈得上「异地登录加验、深夜高危操作收紧、个人设备降权」这些真实风控。

2 · 时间这一维的口径

hourweekday 看着是四个轴里最简单的两个字段,实际最容易写错。首先是时钟的来源:客户端传来的时间戳是可篡改的输入,把它当授权依据等于让请求方自己决定现在几点,只有服务端时钟或可信时间源能进这一维。

其次是时区。「工作时间 9 点到 18 点」对一支跨时区的团队意味着三套不同的区间,拿 UTC 的小时数直接比较,等于给某些地区放宽、给另一些收紧。夏令时切换的那一天,本地 9 点与 UTC 之间的偏移会变一小时,按固定偏移换算的规则当天会整体错一小时,而这类错误只在一年两天里出现,测试很难覆盖到。

警示 · 本系列 policy.tsisWorkHours() 直接读 ctx.hourctx.weekday,模型里没有时区字段。玩具数据这样写足够,真实策略必须把「按谁的本地时间」写进规则本身:是资源所属组织的时区,还是访问者当前所在地的时区?两种口径在同一次跨境访问上给出不同结论。时区与时刻的正确表示见 Temporal 系列。