摘要

  • RFC 9246 要求,普通 CDNI 重定向生成的新令牌必须原样保留已经存在的 exp 和 nbf;原令牌没有这两个声明时,重定向也不能擅自补上。
  • 重定向可以调整签发者、签发时间和适当的接收方、URI 上下文,但新签名与较新的 iat 不等于新的访问时长。
  • 分片令牌续期是另外一种明确启用的机制,使用验证时刻与 cdniets 计算下一个到期值,不能被普通改道操作悄悄替代。
  • exp 并非每个符合该规范的单独令牌都必带。初始准入要求、密钥信任和实际执行的逐请求验证,同样决定时间边界是否有效。
  • 本文分析的是已发布协议及其治理分工,没有复现任何 CDN 缺陷,也没有测量供应商部署范围或事件发生率。

改道不应给已经消耗的时间退款

内容提供方允许一项请求在某个时间之前取得内容。请求到达上游 CDN 后,上游决定让更合适的下游 CDN 完成交付。下游未必认识最初的签发者,也可能需要不同地址,因此中间节点生成新的签名令牌。这是正常的协作动作。

容易混淆的地方在于,“令牌刚刚生成”看起来像“许可刚刚开始”。日志里的签发者是当前节点,签发时间很近,签名也验证成功。三个观察都可以是真的,但它们不能共同推出,访问期限已经获得重新起算的授权。

路径上的时间是已经消耗的时间。若每经过一家 CDN,就按该节点的当前时间再给一整段有效期,改道就变成了延长授权的工具。问题并不要求出现坏签名;有权签名的节点,也可能对自己正在执行的操作理解错误。

RFC 9246 对普通重定向给出的限制相当具体:已有到期值必须保留,不能因为新的交接对象而向后推。新的签名封装可以适应新路径,里面的旧截止线却不能跟着漂移。

标准规定了什么,也没有规定什么

RFC 9246 于 2022 年 6 月发布,在 RFC Editor 的状态记录中属于 Proposed Standard,是 IETF 的标准轨文档。它定义了使用已签名 JWT 支持 URI Signing 的方式,适用于相互连接的内容交付网络,也可以用于单一 CDN 场景。

这不是对所有 CDN 产品的功能清单,更不是某家供应商已经正确实现全部机制的证明。文档规定如何表达和验证请求授权;实际采用的密钥、入口要求、续期安排和控制配置,仍需要结合具体部署理解。

它也不是 DRM。访问控制约束是否允许当前请求取得内容,不会把已经发出的字节收回来。把令牌失效当成内容已经被删除、收件人已经不能再使用副本,属于超出机制能力的承诺。

规范还区分“必须实现某种检查”与“每个令牌必须携带某个声明”。它列出的声明需要得到实现支持,但并非全部都必须用于每个单独的 JWT。URI 容器是必需声明,exp 则是单个令牌中的可选声明。把后一项说成架构上必然存在,会掩盖真正需要配置的准入条件。

若一个服务要求所有初始授权都带截止时间,这可以成为明确的本地接收规则。它不能靠一句“令牌符合 CDNI”来代替,也不能等到改道时再悄悄补一个截止时间,假装原先的授权就是如此。

保留的是时间值,不是声明名称

规范第 2.1.4 节要求,如果收到的 JWT 含有 exp,为 CDNI 重定向生成的后续 JWT 也必须含有 exp,而且值必须相同。原令牌没有 exp,普通重定向不能加上 exp。这是对特定转换动作的要求。

验证同样有清晰边界:内容请求时刻等于或晚于 exp,就必须拒绝;验证方不支持收到的到期声明检查,也必须拒绝。检查到“字段存在”并不足够,数值与请求时刻的关系必须实际参与决定。

nbf 的规则对应另一端。已经存在的值要在重定向中保持不变,没有的也不能新增。请求早于 nbf 时必须拒绝,等于 nbf 则满足这一时间条件。它与 exp 的相等边界不同,不应由笼统的“还在时间窗口里”描述抹平。

禁止给没有 exp 的令牌补上一个短期限,乍看似乎不够积极。其实它提醒了角色边界:普通重定向是在传递收到的授权,不是重新设计授权。如果入口规则认为没有 exp 就不能接受,应在相应入口拒绝,或者由真正拥有授权权力的一方发出新许可。

后者是一项另外获得授权的动作,不是对已有令牌的普通改道。安全性不能只看补出来的数字是否更小,还要看谁有权改变声明集合、改变的依据是什么,以及下游是否把它理解成了原授权的延续。

一个新的 iat 可以配一个旧的 exp

JWT 中的 iat 表示签发时间。CDNI 规范规定,原令牌有 iat 时,重定向的新 JWT 保留这个声明,但数值更新为新 JWT 的生成时刻;原来没有时,也可以加入。因此,新签发时间和旧到期值同时出现,完全可能是正确结果。

签发者也会改变。存在的 iss 要在新重定向令牌中指向执行签名的 CDN。下游需要预先信任的签发者到密钥映射,并检查声明中的签发者与实际签名密钥一致。签名通过不代表任意名称都可以变成可信签发者。

接收方上下文和地址上下文允许相应调整。aud 用于被配置为处理该请求的链路身份,URI 容器可以配合重定向目的地址改变。它们服务于“下一站应该验证什么”,不是“下一站可以任意扩大什么”。

这几种变化并没有带来第四种权力:延长已有 exp。iat 回答新封装有多旧,exp 回答这项授权的时间条件何时结束。将两者机械绑定为“当前签发时间加一段默认时长”,正是需要避免的混同。

JWS 提供签名或消息认证码所需的完整性机制;JWT 的最佳实践则要求对算法、签发者、受众等作适当验证。它们都很重要,但合法密钥可以证明谁签了内容,不能单独证明此人拥有每一种声明转换权限。

规范没有替参与者完成全部密钥信任分配。公钥验证和私钥签发能够分开;对称共享密钥则使持有者不仅能验证,也能生成令牌。CDNI 为兼容保留这种方式,但不建议使用。即使使用非对称方案,对已经可信的签发者仍需要明确限定操作范围。

看似相近的默认宽限,含义并不相同

通用 JWT 允许对 exp 和 nbf 的时钟偏差设置小幅宽限。RFC 9246 的这个应用规范明确禁止时间同步宽限。一个库在其他业务里合理的默认参数,不能未经区分就扩大 CDNI 的可接受窗口。

因此,时间值被正确复制,仍不等于验证边界正确执行。某节点可能保留 exp,却在解释时额外放宽;另一个节点可能精确验证,却在生成时把 exp 向后移。这是两类不同问题,测试应分别观察,而不是统称为签名有效。

规范要求相关签发与验证节点同步时间,并建议使用 NTP。同步并不意味着给路线延迟补回时间,也不使最近一次交接时刻成为新的授权起点。它是让各方以相容时钟判断同一个边界。

原始访问窗口也必须现实。HTTP 交互和临时网络波动需要可用余量,太短的期限会误拒正常用户。余量应体现在已经商定的授权时长里,而不是由每个验证方分别隐藏在自己的宽限参数中。

算术例子不是事故报告

考虑一个纯分析场景:原令牌的逻辑到期时刻是六十,第一站在十时改道,第二站在二十时再次改道。新的签发者和 iat 可以随操作更新,exp 却一直是六十。到了六十五,不能因为第二站的签名比较新,就认为原时间条件仍有效。

若第二站按“二十加六十”把 exp 改为八十,签名可能仍由下游信任的密钥生成,地址也可能正确。错误在于把改道误当成新时长授权。这个例子没有对应已复现的供应商行为,不应写成实际漏洞结论。

相反,若参与者真正启用了分片续期,规则就不同。在五十五验证一个当前有效的令牌,cdniets 是三十,下一个令牌的到期值可以按续期规则算到八十五。它展示的是另一项明确授予的操作,不能拿来解释普通重定向为什么可以改变旧的六十。

两种计算都可能出现在同一个签名组件里。真正需要保留的区别是调用这个组件的授权目的,而不是它们最后是否都输出了一串 JWT。

续期解决的是持续分片访问

分片视频的请求顺序往往无法预先完全确定。播放器可以跳转,也可以改变表现版本。若在清单里为每个片段预先提供覆盖整段播放的长期签名地址,访问表面就可能比必要的更长。

Signed Token Renewal 允许 CDN 在正确验证并成功交付一个片段后,把用于后续相关资源访问的令牌交给客户端。cdniets 表示加到验证时刻上的秒数,用来计算下一令牌的 exp;cdnistt 则表示令牌的传输方式。

使用续期时,这两个声明必须按规范提供。传输值零表示续期传输未启用,不是“虽然没声明但可以随时续”。如果不需要续期,规范建议省略这对声明,而不是让普通改道代码承担隐含的续期职责。

这种滚动窗口能够约束相邻分片之间的访问间隔,却不自动给出全部业务层面的绝对截止线。如果节目、资格或服务安排还要求一个总体结束时刻,参与者需要约定在哪里执行这个条件。

这是治理上的补充问题,不是本文创造了一个已经存在的 IETF 声明,也不是要求内容提供方在线批准每个片段。下游可以在明确授予的续期范围内本地判断;前提是各方知道它获得了什么,而不是把所有新签名都叫续期。

带到哪里,与准许什么,并非一个范围

令牌续期可以通过 cookie,也可以通过查询参数传输。IANA 的 CDNI 参数登记明确列出相应取值。跨域 cookie 的限制可能要求使用查询传输,而规范描述的续期流程要求清单与分片由同一域名交付,跨域改道在取得清单时处理。

路径深度 cdnistd 用于关联后续令牌的传输路径子集。省略时按零理解,零可以使客户端在任何路径上返回令牌。但客户端在哪里附带证明,不等于该证明允许访问那里的一切资源。

授权仍由 URI 容器等条件限制。规范要求用去掉签名包后的请求 URI,并采用百分号编码形式比较。调整 URI 以到达同一授权内容,与扩大匹配范围以覆盖额外内容,是不同决定。

很宽的 URI 容器加上缺乏其他限制,可能形成过宽的通行凭据,规范对此明确不建议。不能由此说所有签名地址都没有边界;需要检查的是实际声明集和接受配置,而不是“用了 JWT 就安全”或“用了 JWT 就危险”的二选一。

验证是否执行,不能从签名外观倒推

内容提供方的分发要求与 CDN 的本地执行通过 CDNI 框架和元数据协作。URI Signing 的 enforce 默认值为真,要求交付前验证。当它为假时,下游不执行验证,即便请求地址看起来带有签名令牌。

这个分支揭示一个容易遗漏的事实:拿到一条签名 URL,并不能证明需要的验证已经运行。它可能反映一个有意关闭验证的配置,也可能与业务预期不一致;本文没有对任何实际部署作此判断。

同样,元数据中的签发者列表为空,不代表信任全互联网。它意味着可信签发者密钥库中的签发者可以被接受。默认值的含义依赖一个已经建立、仍须维护的信任范围。

能力通告和请求路由能够帮助选择支持相关元数据的下游。地理适合、容量可用、声称支持,不是某一项请求正确保留 exp 的证明。逐请求执行和拒绝原因的日志可以补充观察,但单个成功标记仍不能代表每一个声明检查。

重放状态也不会因新封装而消失

存在的 jti 在重定向中也要保持相同,原来没有时不能加入。按照规范,接收这类声明的验证方需要支持使用状态检查,对同一内容的重复使用拒绝访问。只有一个标识字符串而没有相应状态,并不构成重放防护。

状态需要有保留范围与清理方式。规范讨论了依据 exp 结束保留期,以及没有 exp 时采用有界最近最少使用存储的局限;后一种安排最终可能允许标识重新使用。一个共同 jti 也不会自动建立跨所有 CDN 的全球一次性消费账本。

这些条件再次说明,新的签名封装可以承载同一个仍受约束的访问动作。它不会自动洗掉经过的时间、重放历史或尚需执行的条件。谁负责这些限制,需要在交接前而不是交付事故后才确定。

证据来自已发布协议和官方协调机制,未测量实际错误的频率。heng.lu 的最小初始约定、本地未来决策与自愿采用框架提供治理视角,不替代具体令牌处理规则。这里所需的共同承诺可以很小:准确说清改道与续期的边界,让本地自治发生在已经授予的范围内。

来源