工程上最危险的不是完全不可用,而是在理想环境里正常、进入真实网络和真实数据量后悄悄失去边界。 身份令牌回答主体是谁,能力令牌回答持有者可对具体资源做什么。令牌应不可扩大权限,并绑定受众以免在其他服务重放。
安全评审要从资产、攻击者能力和信任边界出发,并在每次状态转换重新授权。输入校验、速率限制和审计只能互补,任何一个都不能替代权限判断。
工程边界与取舍
落地时要把关键选择变成稳定契约:输入如何校验、状态由谁推进、资源何时释放、旧版本如何降级。只有这样,后续优化才不会改变原有语义。
- 声明包含 resourceId、actions、audience、notBefore、expiresAt 和随机 jti;敏感能力短期有效且服务端保留撤销或一次性消费记录。
- 先定义正常、降级、取消和失败四类终态,再让界面、存储与指标消费同一状态。
- 重试必须带幂等键、退避和截止时间;超过截止时间后建立新任务,而不是继续复活旧回调。
“能力令牌设计:授权“能做什么”而不只是“你是谁””的交付标准是正常路径可用、异常路径收敛、资源有界,并且用户能理解系统为何采用当前状态。 这样得到的不是演示代码,而是能解释、能降级、能回滚的生产能力。
生产环境会怎样出错
失败路径需要与成功路径共享同一套状态模型。只弹一个错误提示却不释放资源、不传播终态,下一次恢复就会继承脏状态。
- 只凭难猜 URL 授权会被日志与 Referer 泄露;通配资源或 action 会让本来只看屏幕的令牌获得控制权限。
- 只修正界面状态而没有清理底层资源,下一次操作继承队列、锁或过期凭据并再次失败。
- 指标标签直接包含用户或任务标识,既制造高基数成本,也让诊断数据泄露不必要的身份信息。
把测试跑成闭环
测试不能以“最后成功了”结束。还要测量经历了多少次副作用、等待多久、是否泄露内容,以及失败后再次执行能否从干净基线开始。
- 逐位篡改资源、动作、受众、时间与 jti,并尝试重复使用一次性令牌,确认任何扩权或重放都失败。
- 用乱序、重复和延迟消息驱动状态机,确认旧版本被丢弃且显式停止不会被自动恢复覆盖。
- 用故障注入验证告警先于用户投诉触发,并确认值班人员能从有限证据定位到具体阶段。
最终交付标准应当是:正常路径足够快,异常路径能够收敛,用户意图不会被自动恢复覆盖,运维人员也能从有限而安全的证据定位问题。